Skip to content

Sweep orphaned pending requests on startup and fire their webhooks#1487

Merged
Evanfeenstra merged 1 commit into
mainfrom
reqs-restart-sweep
Jul 24, 2026
Merged

Sweep orphaned pending requests on startup and fire their webhooks#1487
Evanfeenstra merged 1 commit into
mainfrom
reqs-restart-sweep

Conversation

@Evanfeenstra

Copy link
Copy Markdown
Collaborator

Problem

Since #1482, request state survives restarts as .reqs/<id>.json files — but only for runs that reached a terminal state. A restart mid-run left zombies:

  • The disk file stayed {"status":"pending"} forever; nothing resumed the run or marked it failed, so GET /progress pollers hung indefinitely.
  • The webhookUrl terminal callback never fired — delivery only happened from the in-process finish/fail path, and the URL wasn't persisted anywhere.
  • Pre-restart files were never evicted: startReq only evicts ids in the in-memory REQ_ORDER, which dies with the process.

Fix

  • startReq(webhookUrl?) persists the caller's webhook URL into the .reqs file (existing no-arg callers unaffected; checkReq strips it so the /progress response shape is unchanged).
  • sweepOrphanedReqs() (reqs.ts) runs at boot: flips still-pending files to {status: "failed", error: "server restarted while request was in-flight"} and re-adopts all surviving files into the eviction index, oldest first, so pre-restart files churn out under MAX_REQS again.
  • sweepOrphanedRuns() (repo/index.ts) wraps the sweep and POSTs the standard terminal payload to each orphan's recorded webhook via the existing retrying postTerminalWebhook. Invoked from the app.listen callback.

Verified

tsc --noEmit clean. Exercised the sweep against a temp REQS_DIR simulating a restart: pending files (with and without webhook) flipped to failed and returned as orphans with the right webhook URLs, completed files untouched, fresh startReq writes webhookUrl to disk while checkReq omits it.

Note: this covers process restarts; container restarts still need REQS_DIR on a mounted volume for the files to survive at all.

🤖 Generated with Claude Code

A server restart killed in-flight /repo/agent runs but left their .reqs
files at "pending" forever, so pollers hung and webhookUrl callbacks
never fired. Now startReq persists the caller's webhookUrl into the
.reqs file, and a boot-time sweep flips still-pending files to failed,
delivers the terminal webhook for any that registered one, and re-adopts
surviving files into the eviction index so pre-restart files still churn
out under MAX_REQS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Evanfeenstra
Evanfeenstra merged commit 28de808 into main Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant