Skip to content

Add optional open-circuit fallback callable#105

Open
Louisvranderick wants to merge 3 commits into
danielfm:mainfrom
Louisvranderick:feature/circuit-breaker-fallback
Open

Add optional open-circuit fallback callable#105
Louisvranderick wants to merge 3 commits into
danielfm:mainfrom
Louisvranderick:feature/circuit-breaker-fallback

Conversation

@Louisvranderick
Copy link
Copy Markdown

Summary

Adds an optional fallback parameter to CircuitBreaker. When the circuit is open and a fallback is provided, it is called with the original arguments instead of raising CircuitBreakerError. Works for both sync (call) and async (acall) paths, including awaiting async fallbacks. Purely opt-in — omitting it preserves existing raise-on-open behaviour.

Depends on #103 and the decorator/docs PR being merged first.

What changed

  • CircuitBreaker.__init__ accepts fallback: Callable | None.
  • New _open_circuit_fallback_or_raise (sync) and _open_circuit_fallback_or_raise_async methods.
  • CircuitOpenState.before_call and CircuitOpenState.acall delegate to fallback helpers when the timeout has not elapsed.
  • fallback read-only property.
  • README section documenting the feature with examples.
  • CHANGELOG entry.
  • 7 new test cases (sync fallback, no-fallback raise, kwargs forwarding, property, async+sync fallback, async+async fallback, fallback-that-raises propagation).
  • tests/typechecks.py updated for mypy coverage.

Test plan

  • All 103 tests pass
  • mypy and ruff clean

- Add asyncio.Lock (lazy, thread-safe) and async acall() on CircuitBreaker
- Implement state.acall with awaitable support; reject sync/async generators
- CircuitOpenState.acall delegates to half-open without re-entering acall
- Tests: CircuitBreakerAsyncioTestCase (stdlib asyncio.run)
- CHANGELOG: unreleased 1.5.0 note; .gitignore .venv-ci/

Made-with: Cursor
- Add __pybreaker_call_acall kwarg to decorator, wrapping async functions via acall
- Raise ValueError when both __pybreaker_call_async and __pybreaker_call_acall are set
- Add "Native asyncio (stdlib)" section to README with usage examples
- Update features list in README
- Tests: decorator wrapping, partial application, mutual exclusion guard

Made-with: Cursor
Allow users to pass a `fallback` callable to CircuitBreaker that is
invoked with the original arguments when the circuit is open, instead
of raising CircuitBreakerError. Works for both sync `call` and async
`acall` paths. The fallback is purely opt-in — omitting it preserves
existing raise-on-open behaviour.

Made-with: Cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant