feat: exact in-flight concurrency cap via a Durable Object (#4) - #26
Merged
Conversation
The KV breaker bounds rate (audits per minute); nothing bounded
concurrency, so a burst that fit the per-minute budgets could still pile
simultaneous tree-walks onto the shared git token. One ConcurrencyGate
DO (idFromName("global")) now counts in-flight audits exactly and
sheds with 429 past MAX_IN_FLIGHT (6).
Advisory by design, per the issue's fallback criterion: a DO error or
missing binding never blocks an audit — only an explicit at-capacity
answer sheds. The slot ledger is in-memory (a DO is single-threaded, so
it is exact while the object lives; eviction resets to all-free, the
harmless direction), leaked slots self-heal after STALE_MS, and release
is idempotent. SQLite-backed class in the migration — the only kind new
migrations may create on the free plan; it uses no storage.
Verified on workerd via wrangler dev --local in fixture mode: binding
resolves, audits flow through acquire/release.
Closes #4
Co-Authored-By: Claude Fable 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.
Acceptance, against the issue
ConcurrencyGate(one instance viaidFromName("global")) hands out slot tokens up toMAX_IN_FLIGHT(6) and sheds with 429 +retry-after: 10past it; the handler rejects with reason-loggedreject reason=concurrency.get/fetchthrow, or a non-ok non-429 answer all proceed uncapped (the KV per-minute breaker still stands). Only an explicit at-capacity answer sheds.Shape
src/gate.ts: pure, clock-injectedConcurrencySlotsledger (unit-testable without a DO runtime) + the thinConcurrencyGateDO over POST/acquire//release. In-memory only — a DO is single-threaded so the count is exact while it lives, and an eviction resets to all-free, the harmless direction. Leaked slots (a worker that died between acquire and release) self-heal afterSTALE_MS(120s, generously above the fetch layer's caps); release is idempotent.finallyon every path.wrangler.toml: binding +v1migration withnew_sqlite_classes(the only class kind new migrations may create on the free plan; no storage is used).Verification
tsc --noEmit,wrangler deploy --dry-runresolvingenv.GATE.wrangler dev --localin fixture mode — binding active, audit flows through acquire/release.Closes #4
🤖 Generated with Claude Code