Skip to content

Commit c85f9aa

Browse files
committed
feat(procrastinate): record_task_args stores defer kwargs in task data
1 parent bc60bc1 commit c85f9aa

2 files changed

Lines changed: 42 additions & 3 deletions

File tree

taskbadger/procrastinate.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import collections
1515
import functools
1616
import inspect
17+
import json
1718
import logging
1819
from contextvars import ContextVar
1920

@@ -215,9 +216,17 @@ def _maybe_create_pending(task, kwargs):
215216
for key in ("value_max", "tags"):
216217
if key in opts and opts[key] is not None:
217218
create_kwargs[key] = opts[key]
218-
user_data = opts.get("data")
219-
if user_data:
220-
create_kwargs["data"] = dict(user_data)
219+
220+
data = dict(opts.get("data") or {})
221+
222+
record_args = opts.get("record_task_args")
223+
if record_args is None:
224+
record_args = bool(system) and system.record_task_args
225+
if record_args:
226+
data["procrastinate_task_kwargs"] = _serialize_kwargs(kwargs)
227+
228+
if data:
229+
create_kwargs["data"] = data
221230

222231
tb_task = create_task_safe(name, **create_kwargs)
223232
if tb_task is None:
@@ -228,6 +237,19 @@ def _maybe_create_pending(task, kwargs):
228237
return new_kwargs
229238

230239

240+
def _serialize_kwargs(kwargs):
241+
"""Return a JSON-roundtrippable copy of the defer kwargs.
242+
243+
Procrastinate already requires kwargs be JSON-serializable, so a json
244+
dumps/loads roundtrip is safe. Non-serializable values are dropped with
245+
a warning."""
246+
try:
247+
return json.loads(json.dumps(kwargs))
248+
except (TypeError, ValueError) as e:
249+
log.warning("Error serializing task arguments: %s", e)
250+
return {}
251+
252+
231253
_TRACK_OPT_KEYS = ("name", "value_max", "tags", "data", "record_task_args")
232254

233255

tests/test_procrastinate.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,20 @@ def self_complete():
307307
assert StatusEnum.PROCESSING in statuses
308308
# Last attempted SUCCESS call should be suppressed
309309
assert statuses.count(StatusEnum.SUCCESS) == 0
310+
311+
312+
@pytest.mark.usefixtures("_bind_settings")
313+
def test_record_task_args_stores_kwargs(app):
314+
@track(record_task_args=True, data={"existing": 1})
315+
@app.task(name="recorder")
316+
def recorder(a, b):
317+
return a + b
318+
319+
tb = task_for_test()
320+
with mock.patch("taskbadger.procrastinate.create_task_safe", return_value=tb) as create:
321+
recorder.defer(a=5, b=6)
322+
323+
assert create.call_args.kwargs["data"] == {
324+
"existing": 1,
325+
"procrastinate_task_kwargs": {"a": 5, "b": 6},
326+
}

0 commit comments

Comments
 (0)