01 · Before and afterThe pattern
Claim, act, and roll the claim back on failure.
const claimed = await redis.hsetnx(key, "dispatched", 1);
if (!claimed) return "already queued";
try {
await queue.publish(job, { dedupId: `order-${token}` });
} catch (err) {
await redis.hdel(key, "dispatched"); // let the next retry claim it again
throw err; // surface 500 so the sender retries
}02 · Run it on your appThe check
If the call right after you set a “processing” or “done” marker fails, does a retry still do the work?
If the honest answer is no or not sure, this is worth a look before it reaches production.