Make handlers idempotent
Visibility and atomic handoff (for external queues)
in_progress with a worker_id and a locked_until timestamp (or use SELECT ... FOR UPDATE SKIP LOCKED pattern).locked_until expires.so in external queues we don’t need to use locking here ? **
If handler raises and you swallow the error (catch + not requeue), the item is done: queue.task_done() is called and the message is lost (no retry).
If you want retries :
attempts, schedule asyncio.create_task(delayed_reenqueue(...)) which does await asyncio.sleep(backoff) then queue.put_nowait(item). Works while process is alive.outbox.attempts and available_at in DB; leave it to the outbox poller/publisher to pick it up later. This survives process crash.Where to attach metadata:
{"event":"image_uploaded","data":..., "attempts":0, "max_attempts":3, "outbox_id": None}).id, attempts, available_at, status. When the outbox poller claims the row it can create an in-memory item that includes outbox_id.when an outbox poller claims the row will it publish it to queue just like as we are publishing(enqueing) from route