0.10.1 — delta-audit closure (fixes + hardening)#52
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lure-safe + event field M1: AsyncTimeout(timeout=nan|inf) was accepted (<=0 is False for both) — now rejected via `not math.isfinite(timeout) or timeout <= 0`; message updated to "finite number > 0". M2: _emit_event wraps OTel add_event in contextlib.suppress(Exception) so a broken exporter cannot strand circuit-breaker state (permanent HALF_OPEN wedge) or break any request path; CancelledError/KeyboardInterrupt still propagate. H1 enabler: event_name now emitted as structured "event" field on the log record so log-based users can filter by event name; OTel add_event attributes unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eset, boundaries, probe-reopen Closes audit H1, M3, M4, L5-L8: assert the stable event-name strings via the new record.event field; pin exact retry_after; prove 429 resets the failure streak via the StatusError-success branch; sync probe-release mirror; success_threshold>1 with mid-streak probe failure; reset_timeout=0 and empty failure_status_codes; failures=1 on probe-reopen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The prior assertions (handler.calls==7, final 200) held whether or not the success counter was reset on reopen. Rewrite so a missing reset leaves the circuit OPEN at the end and the final request is rejected — verified via a mutation check (removing the reset now fails the test). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, timeout knob) M5 index observability + new loggers/events; M6 README INFO recovery events; L1 AsyncRetry 'no timeout knob' now points to AsyncTimeout; L2 CircuitOpenError in index/README error lists; L3 OPEN-state lazy-transition wording; L4 observability docstring loggers; N2 note TransportError is foreign to the breaker. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Closes the 0.10.0 delta audit (1 High, 6 Medium, 8 Low, 2 nits) as a patch release. No breaking changes; one additive observability field.
Production fixes
AsyncTimeoutrejects non-finite values (M1):timeout=nan|infwas accepted (<= 0isFalsefor both) → nondeterministic / never-firing deadline. Now requires a finite positive number._emit_eventpreviously called OTelspan.add_event(...)unguarded; a raising span propagated into the caller and could strand the circuit breaker permanently in HALF_OPEN. OTel emission now degrades silently on failure (the log record has already fired) — fixed at the root for all middleware.Observability (additive)
eventfield with the event-name string (e.g.event="circuit.opened"). Previously the name reached only OTel span events. Additive — no existing attribute changed.Test hardening
messagesubstring (the name never reached the log record), so a rename passed silently. Now asserted via the neweventfield.retry_aftervalue + clamp (M3); 429-resets-the-failure-streak via the StatusError-success branch (M4); sync probe-release mirror,success_threshold>1mid-streak probe failure (made discriminating via a mutation check),reset_timeout=0, emptyfailure_status_codes,failures=1on probe-reopen (L5–L8).Docs
docs/index.mdobservability section lists all four loggers + events with levels;CircuitOpenErroradded to README/index error lists; README logging example surfaces INFO recovery events; OPEN-state lazy-transition wording and the AsyncRetry timeout-knob note corrected (M5, M6, L1–L4, N2).Verified sound (no change needed)
Async atomicity, sync lock coverage, cross-loop guard,
cm.expired()discriminator, exception-clause disjointness, pickle round-trip, export symmetry, and the property/concurrent tests' soundness all hold.Test Plan
just lint-cicleanjust test— 569 passed, 100% coverageadd_eventswallowed;CancelledErrorstill propagates)🤖 Generated with Claude Code