Skip to content

Commit 59c4ba2

Browse files
authored
Merge pull request #52 from taskbadger/sk/queue
Add queue field support
2 parents 0fdaa01 + cd84b21 commit 59c4ba2

12 files changed

Lines changed: 140 additions & 9 deletions

taskbadger.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,10 @@ components:
690690
minLength: 1
691691
description: Name of the task
692692
maxLength: 255
693+
queue:
694+
type: string
695+
description: Queue the task is from
696+
maxLength: 255
693697
status:
694698
allOf:
695699
- $ref: '#/components/schemas/StatusEnum'
@@ -786,6 +790,10 @@ components:
786790
type: string
787791
description: Name of the task
788792
maxLength: 255
793+
queue:
794+
type: string
795+
description: Queue the task is from
796+
maxLength: 255
789797
status:
790798
allOf:
791799
- $ref: '#/components/schemas/StatusEnum'
@@ -881,6 +889,10 @@ components:
881889
minLength: 1
882890
description: Name of the task
883891
maxLength: 255
892+
queue:
893+
type: string
894+
description: Queue the task is from
895+
maxLength: 255
884896
status:
885897
allOf:
886898
- $ref: '#/components/schemas/StatusEnum'

taskbadger/celery.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ def taskbadger_task(self):
122122

123123
@before_task_publish.connect
124124
def task_publish_handler(sender=None, headers=None, body=None, **kwargs):
125+
routing_key = kwargs.get("routing_key")
125126
headers = headers if "task" in headers else body
126127
header_kwargs = headers.pop(TB_KWARGS_ARG, {}) # always remove TB headers
127128
if sender.startswith("celery.") or not Badger.is_configured():
@@ -144,6 +145,8 @@ def task_publish_handler(sender=None, headers=None, body=None, **kwargs):
144145
# get kwargs from the task headers (set via apply_async)
145146
kwargs.update(header_kwargs)
146147
kwargs["status"] = StatusEnum.PENDING
148+
if routing_key and "queue" not in kwargs:
149+
kwargs["queue"] = routing_key
147150
name = kwargs.pop("name", headers["task"])
148151

149152
global_record_task_args = celery_system and celery_system.record_task_args
@@ -242,7 +245,9 @@ def _maybe_create_task(signal_sender):
242245

243246
enter_session()
244247

245-
task = create_task_safe(task_name, status=StatusEnum.PENDING, data=data)
248+
delivery_info = getattr(signal_sender.request, "delivery_info", None) or {}
249+
queue = delivery_info.get("routing_key")
250+
task = create_task_safe(task_name, status=StatusEnum.PENDING, data=data, queue=queue)
246251
if task:
247252
# Store the task ID in the request so _update_task can find it
248253
signal_sender.request.update({TB_TASK_ID: task.id})

taskbadger/cli/basics.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def create(
5959
),
6060
status: StatusEnum = typer.Option(StatusEnum.PROCESSING, help="The initial status of the task."),
6161
value_max: int = typer.Option(100, help="The maximum value for the task."),
62+
queue: str = typer.Option(None, show_default=False, help="The name of the queue the task is from."),
6263
metadata: list[str] = typer.Option(
6364
None,
6465
show_default=False,
@@ -96,6 +97,7 @@ def create(
9697
actions=actions,
9798
monitor_id=monitor_id,
9899
tags=tags,
100+
queue=queue,
99101
)
100102
except Exception as e:
101103
err_console.print(f"Error creating task: {e}")
@@ -121,6 +123,7 @@ def update(
121123
status: StatusEnum = typer.Option(StatusEnum.PROCESSING, help="The status of the task."),
122124
value: int = typer.Option(None, show_default=False, help="The current task value (progress)."),
123125
value_max: int = typer.Option(None, show_default=False, help="The maximum value for the task."),
126+
queue: str = typer.Option(None, show_default=False, help="The name of the queue the task is from."),
124127
metadata: list[str] = typer.Option(
125128
None,
126129
show_default=False,
@@ -159,6 +162,7 @@ def update(
159162
data=metadata,
160163
actions=actions,
161164
tags=tags,
165+
queue=queue,
162166
)
163167
except Exception as e:
164168
err_console.print(f"Error creating task: {e}")

taskbadger/internal/models/patched_task_request.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class PatchedTaskRequest:
2323
"""
2424
Attributes:
2525
name (str | Unset): Name of the task
26+
queue (str | Unset): Queue the task is from
2627
status (StatusEnum | Unset): * `pending` - pending
2728
* `pre_processing` - pre_processing
2829
* `processing` - processing
@@ -48,6 +49,7 @@ class PatchedTaskRequest:
4849
"""
4950

5051
name: str | Unset = UNSET
52+
queue: str | Unset = UNSET
5153
status: StatusEnum | Unset = StatusEnum.PENDING
5254
value: int | None | Unset = UNSET
5355
value_max: int | Unset = UNSET
@@ -65,6 +67,8 @@ def to_dict(self) -> dict[str, Any]:
6567

6668
name = self.name
6769

70+
queue = self.queue
71+
6872
status: str | Unset = UNSET
6973
if not isinstance(self.status, Unset):
7074
status = self.status.value
@@ -122,6 +126,8 @@ def to_dict(self) -> dict[str, Any]:
122126
field_dict.update({})
123127
if name is not UNSET:
124128
field_dict["name"] = name
129+
if queue is not UNSET:
130+
field_dict["queue"] = queue
125131
if status is not UNSET:
126132
field_dict["status"] = status
127133
if value is not UNSET:
@@ -152,6 +158,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
152158
d = dict(src_dict)
153159
name = d.pop("name", UNSET)
154160

161+
queue = d.pop("queue", UNSET)
162+
155163
_status = d.pop("status", UNSET)
156164
status: StatusEnum | Unset
157165
if isinstance(_status, Unset):
@@ -242,6 +250,7 @@ def _parse_stale_timeout(data: object) -> int | None | Unset:
242250

243251
patched_task_request = cls(
244252
name=name,
253+
queue=queue,
245254
status=status,
246255
value=value,
247256
value_max=value_max,

taskbadger/internal/models/task.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Task:
3131
updated (datetime.datetime):
3232
url (str):
3333
public_url (str):
34+
queue (str | Unset): Queue the task is from
3435
status (StatusEnum | Unset): * `pending` - pending
3536
* `pre_processing` - pre_processing
3637
* `processing` - processing
@@ -64,6 +65,7 @@ class Task:
6465
updated: datetime.datetime
6566
url: str
6667
public_url: str
68+
queue: str | Unset = UNSET
6769
status: StatusEnum | Unset = StatusEnum.PENDING
6870
value: int | None | Unset = UNSET
6971
value_max: int | Unset = UNSET
@@ -98,6 +100,8 @@ def to_dict(self) -> dict[str, Any]:
98100

99101
public_url = self.public_url
100102

103+
queue = self.queue
104+
101105
status: str | Unset = UNSET
102106
if not isinstance(self.status, Unset):
103107
status = self.status.value
@@ -165,6 +169,8 @@ def to_dict(self) -> dict[str, Any]:
165169
"public_url": public_url,
166170
}
167171
)
172+
if queue is not UNSET:
173+
field_dict["queue"] = queue
168174
if status is not UNSET:
169175
field_dict["status"] = status
170176
if value is not UNSET:
@@ -216,6 +222,8 @@ def _parse_value_percent(data: object) -> int | None:
216222

217223
public_url = d.pop("public_url")
218224

225+
queue = d.pop("queue", UNSET)
226+
219227
_status = d.pop("status", UNSET)
220228
status: StatusEnum | Unset
221229
if isinstance(_status, Unset):
@@ -314,6 +322,7 @@ def _parse_stale_timeout(data: object) -> int | None | Unset:
314322
updated=updated,
315323
url=url,
316324
public_url=public_url,
325+
queue=queue,
317326
status=status,
318327
value=value,
319328
value_max=value_max,

taskbadger/internal/models/task_request.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class TaskRequest:
2323
"""
2424
Attributes:
2525
name (str): Name of the task
26+
queue (str | Unset): Queue the task is from
2627
status (StatusEnum | Unset): * `pending` - pending
2728
* `pre_processing` - pre_processing
2829
* `processing` - processing
@@ -48,6 +49,7 @@ class TaskRequest:
4849
"""
4950

5051
name: str
52+
queue: str | Unset = UNSET
5153
status: StatusEnum | Unset = StatusEnum.PENDING
5254
value: int | None | Unset = UNSET
5355
value_max: int | Unset = UNSET
@@ -65,6 +67,8 @@ def to_dict(self) -> dict[str, Any]:
6567

6668
name = self.name
6769

70+
queue = self.queue
71+
6872
status: str | Unset = UNSET
6973
if not isinstance(self.status, Unset):
7074
status = self.status.value
@@ -124,6 +128,8 @@ def to_dict(self) -> dict[str, Any]:
124128
"name": name,
125129
}
126130
)
131+
if queue is not UNSET:
132+
field_dict["queue"] = queue
127133
if status is not UNSET:
128134
field_dict["status"] = status
129135
if value is not UNSET:
@@ -154,6 +160,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
154160
d = dict(src_dict)
155161
name = d.pop("name")
156162

163+
queue = d.pop("queue", UNSET)
164+
157165
_status = d.pop("status", UNSET)
158166
status: StatusEnum | Unset
159167
if isinstance(_status, Unset):
@@ -244,6 +252,7 @@ def _parse_stale_timeout(data: object) -> int | None | Unset:
244252

245253
task_request = cls(
246254
name=name,
255+
queue=queue,
247256
status=status,
248257
value=value,
249258
value_max=value_max,

taskbadger/procrastinate.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,14 @@ async def defer_async(**kwargs):
160160
task.defer_async = defer_async
161161

162162

163-
def _create_pending_task(task, task_kwargs):
163+
def _create_pending_task(task, task_kwargs, queue=None):
164164
"""Create a PENDING TaskBadger task for ``task`` if it should be tracked.
165165
166166
Returns the created TaskBadger task, or ``None`` if Badger isn't
167167
configured, the task isn't tracked (neither manual nor auto), or the
168168
create call failed. ``task_kwargs`` is used only for the
169-
``record_task_args`` data capture.
169+
``record_task_args`` data capture. ``queue`` overrides the queue name
170+
recorded on the TaskBadger task (defaults to the task's own queue).
170171
"""
171172
if not Badger.is_configured():
172173
return None
@@ -180,6 +181,9 @@ def _create_pending_task(task, task_kwargs):
180181
opts = dict(getattr(task, _OPTS_ATTR, {}) or {})
181182
name = opts.pop("name", None) or task.name
182183
create_kwargs = {"status": StatusEnum.PENDING}
184+
queue = queue or getattr(task, "queue", None)
185+
if queue is not None:
186+
create_kwargs["queue"] = queue
183187
for key in ("value_max", "tags"):
184188
if key in opts and opts[key] is not None:
185189
create_kwargs[key] = opts[key]
@@ -293,7 +297,7 @@ def _patch_job_manager(app, system):
293297
async def patched(*, job, periodic_id, defer_timestamp):
294298
task = app.tasks.get(job.task_name)
295299
if task is not None:
296-
tb_task = _create_pending_task(task, job.task_kwargs)
300+
tb_task = _create_pending_task(task, job.task_kwargs, queue=job.queue)
297301
if tb_task is not None:
298302
new_kwargs = {**job.task_kwargs, TB_TASK_ID_KWARG: tb_task.id}
299303
job = job.evolve(task_kwargs=new_kwargs)

taskbadger/sdk.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ def create_task(
151151
actions: list[Action] = None,
152152
monitor_id: str = None,
153153
tags: dict[str, str] = None,
154+
queue: str = None,
154155
) -> "Task":
155156
"""Create a Task.
156157
@@ -165,6 +166,7 @@ def create_task(
165166
actions: Task actions.
166167
monitor_id: ID of the monitor to associate this task with.
167168
tags: Dictionary of namespace -> value tags.
169+
queue: Name of the queue the task is from.
168170
169171
Returns:
170172
Task: The created Task object.
@@ -173,6 +175,8 @@ def create_task(
173175
"name": name,
174176
"status": status,
175177
}
178+
if queue is not None:
179+
task_dict["queue"] = queue
176180
if value is not None:
177181
task_dict["value"] = value
178182
if value_max is not None:
@@ -216,6 +220,7 @@ def update_task(
216220
stale_timeout: int = None,
217221
actions: list[Action] = None,
218222
tags: dict[str, str] = None,
223+
queue: str = None,
219224
) -> "Task":
220225
"""Update a task.
221226
Requires only the task ID and fields to update.
@@ -231,6 +236,7 @@ def update_task(
231236
stale_timeout: Maximum allowed time between updates (seconds).
232237
actions: Task actions.
233238
tags: Dictionary of namespace -> value tags.
239+
queue: Name of the queue the task is from.
234240
235241
Returns:
236242
Task: The updated Task object.
@@ -242,6 +248,7 @@ def update_task(
242248
data = _none_to_unset(data)
243249
max_runtime = _none_to_unset(max_runtime)
244250
stale_timeout = _none_to_unset(stale_timeout)
251+
queue = _none_to_unset(queue)
245252

246253
data = data or UNSET
247254
body = PatchedTaskRequest(
@@ -252,6 +259,7 @@ def update_task(
252259
data=data,
253260
max_runtime=max_runtime,
254261
stale_timeout=stale_timeout,
262+
queue=queue,
255263
)
256264
if actions:
257265
body.additional_properties = {"actions": [a.to_dict() for a in actions]}
@@ -314,6 +322,7 @@ def create(
314322
actions: list[Action] = None,
315323
monitor_id: str = None,
316324
tags: dict[str, str] = None,
325+
queue: str = None,
317326
) -> "Task":
318327
"""Create a new task
319328
@@ -330,6 +339,7 @@ def create(
330339
actions=actions,
331340
monitor_id=monitor_id,
332341
tags=tags,
342+
queue=queue,
333343
)
334344

335345
def __init__(self, task):
@@ -414,6 +424,7 @@ def update(
414424
stale_timeout: int = None,
415425
actions: list[Action] = None,
416426
tags: dict[str, str] = None,
427+
queue: str = None,
417428
data_merge_strategy: Any = None,
418429
):
419430
"""Generic update method used to update any of the task fields.
@@ -441,6 +452,7 @@ def update(
441452
stale_timeout=stale_timeout,
442453
actions=actions,
443454
tags=tags,
455+
queue=queue,
444456
)
445457
self._task = task._task
446458

0 commit comments

Comments
 (0)