SPB Git

spb/ai-atlas

Public

admin requeue-dead: honour the dedupe partial unique index

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Sep 12, 2026) parent 8a8af96 Browse files

1 changed file +11 −3

Unified Split
modified src/aiatlas/api/routers/admin.py +11 −3
@@ -262,10 +262,18 @@ async def retry_job(job_id: str) -> dict[str, Any]:
262 262
263 @router.post("/jobs/requeue-dead") 263 @router.post("/jobs/requeue-dead")
264 async def requeue_dead(kind: str | None = None) -> dict[str, Any]: 264 async def requeue_dead(kind: str | None = None) -> dict[str, Any]:
265− where = "status = 'dead'" + (" and kind = :k" if kind else "") 265+ where = "j.status = 'dead'" + (" and j.kind = :k" if kind else "")
266 async with transaction() as conn: 266 async with transaction() as conn:
267− n = await fetch_val(conn, f"with u as (update jobs set status = 'queued', attempts = 0, error = null, locked_by = null, locked_at = null, finished_at = null, run_after = now() " 267+ # respect the partial unique index on dedupe_key (queued|running): skip dead jobs already superseded by a live one,
268− f"where {where} returning 1) select count(*) from u", k=kind) 268+ # and requeue only one dead job per dedupe_key (the most recent); the other duplicates are closed as superseded.
269+ n = await fetch_val(conn, f"""with pick as (
270+ select distinct on (coalesce(j.dedupe_key, j.id)) j.id from jobs j
271+ where {where} and (j.dedupe_key is null or not exists (select 1 from jobs q where q.dedupe_key = j.dedupe_key and q.status in ('queued','running')))
272+ order by coalesce(j.dedupe_key, j.id), j.created_at desc),
273+ u as (update jobs set status = 'queued', attempts = 0, error = null, locked_by = null, locked_at = null, finished_at = null, run_after = now()
274+ where id in (select id from pick) returning 1)
275+ select count(*) from u""", k=kind)
276+ await execute(conn, f"update jobs j set status = 'done', error = coalesce(error, '') || ' [superseded]' where {where}", k=kind)
269 return {"requeued": int(n or 0)} 277 return {"requeued": int(n or 0)}
270 278
271 279
272 280
Menu

Theme