Repository navigation
fix(pipeline): circuit-break the event categoriser on repeated failure - #104
Merged
Merged
Conversation
Categoriser failures are deliberately not cached, so a flaky call
retries on the next run. That is right for a transient glitch and
ruinous for a persistent one: when the provider is unreachable or
misrouted, every uncached event fails and the whole backlog re-fires
every run, indefinitely.
Observed in production as batches of exactly 70 identical failures per
pipeline run across several days:
status_code: 404, model_name: arandu-pro,
body: {'message': "model 'arandu-pro' not found", ...}
In cloud mode each retry is a paid round trip, so a misroute bills the
user repeatedly for calls that cannot succeed. The per-run cap
(_MAX_LLM_CALLS_PER_RUN = 200) does not help: 70 is well under it.
Consecutive failures are the signal. One event failing is that event's
problem; three in a row is the provider's, and every remaining event
will fail the same way. On tripping, the rest of the run takes the
fallback category without spending a call — the same behaviour the
per-run cap already has, so the marts still get a complete row set.
Deliberately unchanged: failures are still not cached, so a recovered
provider re-categorises rather than inheriting fallbacks. The breaker
bounds one run; it does not persist across runs.
The run summary now reports when the breaker tripped, because the
previous incident went undiagnosed for days partly for lack of any
such signal.
Four tests, including one that pins the call count to the limit rather
than the event count — it fails without the breaker.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Categoriser failures are deliberately not cached, so a flaky call retries next run:
# Don't cache fallback verdicts — we want to retry next run.Right for a transient glitch. Ruinous for a persistent one: when the provider is unreachable or misrouted, every uncached event fails and the whole backlog re-fires on every run, forever.
Observed in production — batches of exactly 70 identical failures per pipeline run, across several days:
In cloud mode each retry is a paid round trip, so a misroute bills repeatedly for calls that cannot succeed. The existing per-run cap doesn't help — it's 200, and 70 is well under it.
(The misroute itself is fixed separately in arandupro#72. This PR is about not amplifying the next one.)
Fix
Consecutive failures are the signal. One event failing is that event's problem; three in a row is the provider's, and every remaining event will fail identically. On tripping, the rest of the run takes the fallback category without spending a call — the same behaviour the per-run cap already has, so the marts still receive a complete row set.
Effect on the observed incident: 70 failed calls per run → 3.
Deliberately unchanged
Observability
The run summary now reports when the breaker tripped. The previous incident went undiagnosed for days partly because nothing in the logs distinguished "provider down" from "70 bad events".
Tests
Four, including one that pins the call count to the failure limit rather than the event count — it fails without the breaker, verified by neutralising the limit.
2,978 passed; the 5 failures are the pre-existing WhatsApp bridge ones that fail identically on a clean tree.🤖 Generated with Claude Code