test: property-check the circuit breaker's availability contract#592
test: property-check the circuit breaker's availability contract#592ndycode wants to merge 2 commits into
Conversation
Five fast-check properties over the real CircuitBreaker under fake timers (small windows so sequences cross every boundary): - isAvailable/getTimeUntilAvailable agree with the very next canExecute outcome after ANY event sequence - the polling view callers route on is a faithful prediction, never stale - an open circuit rejects strictly before resetTimeoutMs and admits the probe exactly at it, from any prior history (fresh forced open) - opens exactly at failureThreshold inside one window, never below - failures spaced beyond failureWindowMs never accumulate - the half-open slot admits exactly one probe; success closes with a clean failure count, failure reopens for a full timeout Companion to the property suites in #574/#575/#579; same conventions. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
Warning Review limit reached
More reviews will be available in 1 minute and 23 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
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 |
Summary
lib/circuit-breaker.ts— the per-account failure-isolation state machine that rotation uses to decide routability. The existing example suite (28 tests) covers specific paths; this companion pins the contracts that have to hold under any interleaving of failures, successes, attempts, and clock advances.What Changed
New
test/property/circuit-breaker.property.test.ts(5 properties, realCircuitBreakerundervi.useFakeTimers()with small windows so generated sequences cross every timing boundary):isAvailable(now)andgetTimeUntilAvailable(now)agree with what the very nextcanExecute()actually does (allows vs throwsCircuitOpenError), andwait === 0 ⇔ available. This is the load-bearing one: rotation polls the availability view to route accounts, so a stale or disagreeing answer would mis-route.resetTimeoutMs(withgetTimeUntilAvailablereturning the exact remainder) and admits the half-open probe at exactlyresetTimeoutMs.failureThreshold, never below it.failureWindowMsnever accumulate; the circuit stays closed with a count of 1 regardless of how many arrive.One harness bug was caught by fast-check itself during development (property 2 originally assumed the breaker wasn't already open after the arbitrary prefix — counterexample found on run 14); the fix forces a fresh timestamped open, which also strengthens the property to "reset + threshold failures always yields a clean open from any history". No SUT bugs found — the breaker's timing contract held everywhere.
Validation
npm test -- test/property/circuit-breaker.property.test.ts test/circuit-breaker.test.ts— 33/33 (new 5 + existing 28 untouched)npm run typecheck(also via pre-commit hook)npx eslint test/property/circuit-breaker.property.test.ts --max-warnings=0try/finally vi.useRealTimers()plus a guardafterEach, matching the repo's wall-clock test conventionsDocs and Governance Checklist
Risk and Rollback
test/property/suites (test: property-check the unsupported-model fallback invariants #574, test: property-check write-queue serialization and clamp invariants #575, fix: deduplicateAccounts fixpoint loop and identity property tests #579 companions: explicit vitest imports, plainfc.assert).https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
Generated by Claude Code
note: greptile review for oc-chatgpt-multi-auth. cite files like
lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.Greptile Summary
adds a fast-check property suite for
lib/circuit-breaker.ts, complementing the existing 28 example-based tests with 5 contracts that must hold under any interleaving of failures, successes, and clock advances. fake-timer scoping, import style, andfc.assertusage all match repo conventions.isAvailable(now)/getTimeUntilAvailable(now)are a faithful prediction of the very nextcanExecute()call — the contract rotation depends on for account routing.getTimeUntilReset()under fake timers), threshold triggering, failure-window expiry, and half-open probe discipline across arbitrary prior history.reset()+ threshold-failures pattern used in property 2.Confidence Score: 5/5
additive test-only change with no SUT modifications; safe to merge.
the change is a single new test file with no modifications to production code. all five properties are logically sound against the SUT implementation, fake-timer scoping follows the repo's try/finally + afterEach convention, and the previously flagged getTimeUntilReset() gap is now covered in property 2.
no files require special attention.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[arbSequence prefix] --> B{force open\nreset + threshold failures} B --> C[prop 1: isAvailable/getTimeUntilAvailable\nagrees with canExecute] B --> D[prop 2: open-state timing exact\nearlyMs < resetTimeout → reject\nat resetTimeout → half-open probe] B --> E[prop 3: threshold exactness\nopens at exactly failureThreshold] B --> F[prop 4: window expiry\ngaps > failureWindowMs → count stays 1] B --> G[prop 5: half-open probe discipline\none probe admitted; success→closed; failure→open] D --> H{getTimeUntilReset} H -->|open state| I[resetTimeoutMs - elapsed] H -->|non-open state| J[0]Reviews (2): Last reviewed commit: "test: pin getTimeUntilReset alongside th..." | Re-trigger Greptile