fix(runner): laat waitForEnqueue echt tot de deadline wachten #63
No reviewers
Labels
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
janpeter/scrum4me-docker!63
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/wait-for-enqueue-single-shot"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
De bug
waitForEnqueuekeerde onvoorwaardelijk terug na de eerste tick:De inner promise resolvet op een matchende NOTIFY of op de poll-timer. Door de
returngaf de functie dus naPOLL_INTERVAL_MS(5s) op, en waswhile (Date.now() < deadline)dode code — de 270s werd nooit gehaald.De caller deed daarna nog één claim-poging en logde
claim timeout after 270s — exiting 0. Dat was onwaar: het waren ~5 seconden. Het proces exitte, de supervisor startte het opnieuw, en zo cyclede elke worker een compleet nieuw proces per ~8s — met per keer een eigenregisterWorker, auth-check, Prisma-pool en LISTEN-verbinding.Gemeten op max2 (agent-codex, idle queue): 421 runs in uur 08, 323 in uur 09. NOTIFY leverde effectief niets op; de latency was puur poll-gedreven via procesherstarts.
De fix
Na elke tick opnieuw claimen, binnen één LISTEN-verbinding, tot er werk is of de deadline verstrijkt.
Bewust niet alleen de
returnweggehaald: dan zou bij een gemiste NOTIFY 270s lang geen enkele claim-poging gedaan worden — dat maakt de latency juist slechter. De poll blijft het vangnet voor een NOTIFY die we niet kúnnen zien (job stond al in de queue vóór deLISTEN), dus de worst-case latency blijft ~5s, nu zonder procesherstart. Declaim timeout after 270s-regel klopt voortaan.Tweede bug, meegefixt: de listener werd alleen op het NOTIFY-pad verwijderd. Zolang de functie single-shot was viel dat niet op; met een echte loop stapelt elke poll-tick een listener op de langlevende client.
finish()ruimt nu in beide paden op.Structuur
De tick/claim-loop staat nu in
lib/wait-for-enqueue.ts— conform de bestaandelib/-conventie (pure, testbare logica;run-one-job.tsroeptmain()aan bij import en is niet importeerbaar).connect/LISTEN/endblijft in de runner.Verificatie
npx vitest run→ 16/16 groen (5 nieuwe tests).De tests vangen beide bugs aantoonbaar — ik heb ze los teruggezet:
returnterugGedekt: doorclaimen bij elke poll-tick, directe claim bij NOTIFY zonder de poll af te wachten,
nullop de deadline, geen listener-lek, en negeren van NOTIFY voor een andere user / ander type / onparseerbare payload.Effect op DB-connecties
Het aantal gelijktijdige verbindingen per worker verandert niet (~2: Prisma-pool + LISTEN-client), maar ze worden nu vastgehouden i.p.v. elke ~8s opnieuw opgebouwd. De connect-storm verdwijnt; gemiddeld per worker gaat het van ~60% duty-cycle naar ~100% (dus ~+0,8 verbinding per worker, verwaarloosbaar tegen
max_connections), tegenover ~450 connect/disconnect-cycli per uur minder.Uitrol
Vergt image-rebuild + recreate (
redeploy_all_workers);bin/enlib/zijn image-baked.Verdict: APPROVED
Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.
Findings
De wijziging houdt de LISTEN/DB-koppeling in
bin/run-one-job.tsen verplaatst de herbruikbare wacht-/claim-loop naar een pure helper met gerichte regressietests. De testset dekt de kernbug (single-shot wait), NOTIFY-pad, deadline-pad, listener-cleanup en genegeerde payloads.