fix(supervisor): hold the last backpressure verdict when a read fails - #4444
fix(supervisor): hold the last backpressure verdict when a read fails#4444nicktrn wants to merge 4 commits into
Conversation
|
WalkthroughBackpressure monitoring now treats failed verdict reads as outages. It increments a failure counter, logs one error per outage, and retains the last verdict when 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 46b25d12-819d-4881-a493-b7812e34ee43
📒 Files selected for processing (1)
.server-changes/backpressure-hold-last-verdict.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: typecheck / typecheck
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-05-14T14:54:39.095Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3545
File: .server-changes/agent-view-sessions.md:10-10
Timestamp: 2026-05-14T14:54:39.095Z
Learning: In the `trigger.dev` repository, do not flag inconsistent dot vs slash notation in route/path strings inside `.server-changes/*.md` files. These markdown files are consumed verbatim into the changelog, so the mixed notation (e.g., `resources.orgs.../runs.$runParam/...`) is intentional and should be preserved as-is.
Applied to files:
.server-changes/backpressure-hold-last-verdict.md
📚 Learning: 2026-07-26T13:14:02.968Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 4378
File: .server-changes/realtime-run-reads-from-primary.md:0-0
Timestamp: 2026-07-26T13:14:02.968Z
Learning: For files in the .server-changes directory, the body text is published verbatim as dashboard-facing user release notes. Write entries in terms of user-visible behavior (what users can do/see), and avoid implementation-oriented details such as environment-variable names, internal mechanisms, or configuration knobs. If you need to include operational/configuration specifics, put those details in the PR description instead of the .server-changes entry.
Applied to files:
.server-changes/backpressure-hold-last-verdict.md
The dequeue brake released the moment its signal became unreadable.
refresh()caught any error fromsource.read()and set the verdict tonull, whichcomputeEngaged()treats as not-engaged — so a few failed reads dropped an engaged brake, silently, with no log and no metric.That handling was symmetric while the risk is not. A source that has stopped answering correlates with the pressure the brake exists for, so releasing on read failure gives up protection at exactly the wrong moment; holding too long only costs throughput.
Now a failed read keeps the last verdict instead of discarding it. The verdict then ages normally, so the existing
maxVerdictAgeMscheck becomes the grace window and still bounds how long a dead source can hold the brake — a permanently unreachable source releases it rather than pinning dequeuing forever. BecausecomputeEngaged()only consults staleness for an engaged verdict, a released one is unaffected and stays released.The default grace moves from 15s to 120s, comparable to how long the brake normally stays engaged.
One guard worth calling out: holding is only safe when something bounds it, so when
maxVerdictAgeMsis unset the previous discard behaviour is kept. Otherwise an unbounded hold could pin the brake indefinitely.Read failures were previously invisible — the catch block neither logged nor counted. Adds a
read_failures_totalcounter, plus an error log on the transition into failure rather than once per tick, since the refresh loop runs every second.The post-release ramp needs no change: it anchors off the engaged-to-released transition, so a grace-window release still ramps back up instead of snapping to full rate, which is what you want after a blind period.
Tests cover holding while reads fail, releasing past the max age, and the existing unbounded-config paths are unchanged.