mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
_persist_respawn_record is fire-and-forget per gate mutation; a respawn loop fires count 1->2->3->4 in quick succession, scheduling one persist per increment for the same (agent_slug, task_id). The ON CONFLICT DO UPDATE upsert is row-level race-free, but the fire-and-forget tasks can still COMMIT out of order: a slow stale persist (count=2) scheduled first can resolve AFTER a fast fresh one (count=4) scheduled second, leaving the durable row at the stale low count and re-burning the strike threshold on restart. Fix: acquire self._respawn_persist_lock (new asyncio.Lock) as the FIRST await in _persist_respawn_record, so acquisition order = task creation order (FIFO ready queue) = logical schedule order, and commits land in that order. The durable row always ends at the latest logical value. The lock lives in the bg task, so the dispatcher hot path never blocks; persists are best-effort and a slow one queuing the rest just delays the durable catch-up (in-memory record stays authoritative).