How to avoid enqueuing the same task twice¶
This guide shows you how to make spawn_task safe to call more than once
for what is logically the same piece of work: a retried API request, a
redelivered webhook, a script that might run twice by mistake.
Pass an idempotency key¶
engine.spawn_task(
name="charge_card",
params={"order_id": order_id, "amount_cents": 4200},
idempotency_key=f"charge:{order_id}",
)
Choose a key that uniquely identifies the logical operation, not the call site: here, the order being charged, not a random UUID generated per call (that would defeat the purpose).
Check whether it was actually created¶
spawn_task always returns a TaskRef, whether or not it created a new
task:
ref = engine.spawn_task(name="charge_card", params={...}, idempotency_key=key)
if not ref.created:
print(f"already enqueued as {ref.task_id}")
When a task already exists for that key, no new task or run is created.
ref.task_id and ref.run_id point at the existing ones instead.
Collapse duplicates created before you added a key¶
If duplicate tasks with the same name were already enqueued, for example
before you introduced an idempotency_key, clean them up once at
startup:
This keeps the oldest non-terminal task with that name and cancels the
rest. It's meant for a one-off cleanup, not routine use. Going forward,
prevent duplicates at the source with idempotency_key instead.