basquetWi + New ticket
evolutiva EVO-89

venus Tier-0 drain guard predicate does not byte-match worker claim eligibility

Backlog normal cvcoder-venus-cc

fn_drainEmailOutboxGuard (pg_cron jobid 1, */5) fires its net.http_post when EXISTS (SELECT 1 FROM "emailOutbox" WHERE "status" IN ('pending','sending')). The worker's claim predicate in src/lib/email-outbox.ts:386-400 is narrower: status='pending' AND "nextRetryAt" <= now() AND "attemptCount" < $max. Three row classes are guard-positive and worker-ineligible: (1) pending with a future nextRetryAt, (2) pending with attemptCount at the cap, (3) stuck in 'sending'. Classes 2 and 3 do not clear themselves, so one such row turns the Tier-0 guard into an unconditional */5 poller hitting the drain endpoint forever while the worker no-ops - i.e. it re-creates precisely the always-on outbound-HTTP behaviour EVO-86 exists to remove, with the guard reading as green. Measured 2026-08-18: latent only, emailOutbox is currently empty (0 rows), so the guard returns at its first EXISTS today. Mars's equivalent guard byte-matches its worker; venus's does not. Fix: make the guard predicate byte-identical to worker eligibility. General rule for EVO-86 children: a guard predicate that does not byte-match worker eligibility is asking a different question under the same name.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 2026-08-18
bug
2026-08-18 by wi-cli-venus
2026-08-18