Resilience
provide.foundation.resilience
¶
TODO: Add module docstring.
Classes¶
AsyncCircuitBreaker
¶
AsyncCircuitBreaker(
failure_threshold: int = 5,
recovery_timeout: float = 30.0,
expected_exception: (
type[Exception] | tuple[type[Exception], ...]
) = Exception,
time_source: Callable[[], float] | None = None,
)
Asynchronous circuit breaker for resilience patterns.
Uses asyncio.Lock for async-safe state management. For synchronous code, use SyncCircuitBreaker instead.
Initialize the asynchronous circuit breaker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
failure_threshold
|
int
|
Number of failures before opening circuit |
5
|
recovery_timeout
|
float
|
Seconds to wait before attempting recovery |
30.0
|
expected_exception
|
type[Exception] | tuple[type[Exception], ...]
|
Exception type(s) to catch |
Exception
|
time_source
|
Callable[[], float] | None
|
Optional callable that returns current time (for testing). Defaults to time.time() for production use. |
None
|
Source code in provide/foundation/resilience/circuit_async.py
Functions¶
call
async
¶
Execute an asynchronous function through the circuit breaker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable
|
Async callable to execute |
required |
*args
|
Any
|
Positional arguments for func |
()
|
**kwargs
|
Any
|
Keyword arguments for func |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
Result from func |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If circuit is open |
Exception
|
Whatever exception func raises |
Source code in provide/foundation/resilience/circuit_async.py
failure_count
async
¶
reset
async
¶
Reset the circuit breaker to its initial state.
state
async
¶
Get the current state of the circuit breaker.
Returns:
| Type | Description |
|---|---|
CircuitState
|
Current circuit state |
Source code in provide/foundation/resilience/circuit_async.py
Bulkhead
¶
Bulkhead isolation pattern for protecting resources.
Can use either SyncResourcePool or AsyncResourcePool depending on use case.
Functions¶
execute
¶
Execute function with bulkhead protection (sync).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable[..., T]
|
Function to execute |
required |
*args
|
Any
|
Function arguments |
()
|
**kwargs
|
Any
|
Function keyword arguments |
{}
|
Returns:
| Type | Description |
|---|---|
T
|
Function result |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If resource cannot be acquired |
Exception
|
Any exception from the protected function |
Source code in provide/foundation/resilience/bulkhead.py
execute_async
async
¶
Execute async function with bulkhead protection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable[..., Awaitable[T]]
|
Async function to execute |
required |
*args
|
Any
|
Function arguments |
()
|
**kwargs
|
Any
|
Function keyword arguments |
{}
|
Returns:
| Type | Description |
|---|---|
T
|
Function result |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If resource cannot be acquired |
Exception
|
Any exception from the protected function |
Source code in provide/foundation/resilience/bulkhead.py
get_status
¶
Get bulkhead status (sync only).
Source code in provide/foundation/resilience/bulkhead.py
get_status_async
async
¶
Get bulkhead status (async).
Source code in provide/foundation/resilience/bulkhead.py
BulkheadManager
¶
Manager for multiple bulkheads with different resource pools.
Initialize bulkhead manager.
Source code in provide/foundation/resilience/bulkhead.py
Functions¶
create_bulkhead
¶
create_bulkhead(
name: str,
max_concurrent: int = 10,
max_queue_size: int = 100,
timeout: float = 30.0,
use_async_pool: bool = False,
) -> Bulkhead
Create or get a bulkhead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Bulkhead name |
required |
max_concurrent
|
int
|
Maximum concurrent operations |
10
|
max_queue_size
|
int
|
Maximum queue size |
100
|
timeout
|
float
|
Operation timeout |
30.0
|
use_async_pool
|
bool
|
If True, create AsyncResourcePool; otherwise SyncResourcePool |
False
|
Returns:
| Type | Description |
|---|---|
Bulkhead
|
Bulkhead instance |
Source code in provide/foundation/resilience/bulkhead.py
get_all_status
¶
get_bulkhead
¶
list_bulkheads
¶
FallbackChain
¶
Chain of fallback strategies for graceful degradation.
Executes fallback functions in order when primary function fails.
Functions¶
add_fallback
¶
Add a fallback function to the chain.
Source code in provide/foundation/resilience/fallback.py
execute
¶
Execute primary function with fallback chain (sync).
Source code in provide/foundation/resilience/fallback.py
execute_async
async
¶
Execute primary function with fallback chain (async).
Source code in provide/foundation/resilience/fallback.py
RetryExecutor
¶
RetryExecutor(
policy: RetryPolicy,
on_retry: (
Callable[[int, Exception], None] | None
) = None,
time_source: Callable[[], float] | None = None,
sleep_func: Callable[[float], None] | None = None,
async_sleep_func: (
Callable[[float], Awaitable[None]] | None
) = None,
)
Unified retry execution engine.
This executor handles the actual retry loop logic for both sync and async functions, using a RetryPolicy for configuration. It's used internally by both the @retry decorator and RetryMiddleware.
Initialize retry executor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy
|
RetryPolicy
|
Retry policy configuration |
required |
on_retry
|
Callable[[int, Exception], None] | None
|
Optional callback for retry events (attempt, error) |
None
|
time_source
|
Callable[[], float] | None
|
Optional callable that returns current time (for testing). Defaults to time.time() for production use. |
None
|
sleep_func
|
Callable[[float], None] | None
|
Optional synchronous sleep function (for testing). Defaults to time.sleep() for production use. |
None
|
async_sleep_func
|
Callable[[float], Awaitable[None]] | None
|
Optional asynchronous sleep function (for testing). Defaults to asyncio.sleep() for production use. |
None
|
Source code in provide/foundation/resilience/retry.py
Functions¶
execute_async
async
¶
Execute asynchronous function with retry logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable[..., Awaitable[T]]
|
Async function to execute |
required |
*args
|
Any
|
Positional arguments for func |
()
|
**kwargs
|
Any
|
Keyword arguments for func |
{}
|
Returns:
| Type | Description |
|---|---|
T
|
Result from successful execution |
Raises:
| Type | Description |
|---|---|
Exception
|
The last exception raised if all retry attempts are exhausted |
Source code in provide/foundation/resilience/retry.py
execute_sync
¶
Execute synchronous function with retry logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable[..., T]
|
Function to execute |
required |
*args
|
Any
|
Positional arguments for func |
()
|
**kwargs
|
Any
|
Keyword arguments for func |
{}
|
Returns:
| Type | Description |
|---|---|
T
|
Result from successful execution |
Raises:
| Type | Description |
|---|---|
Exception
|
The last exception raised if all retry attempts are exhausted |
Source code in provide/foundation/resilience/retry.py
RetryPolicy
¶
Configuration for retry behavior.
This policy can be used with both the @retry decorator and transport middleware, providing a unified configuration model for all retry scenarios.
Attributes:
| Name | Type | Description |
|---|---|---|
max_attempts |
int
|
Maximum number of retry attempts (must be >= 1) |
backoff |
BackoffStrategy
|
Backoff strategy to use for delays |
base_delay |
float
|
Base delay in seconds between retries |
max_delay |
float
|
Maximum delay in seconds (caps exponential growth) |
jitter |
bool
|
Whether to add random jitter to delays (±25%) |
retryable_errors |
tuple[type[Exception], ...] | None
|
Tuple of exception types to retry (None = all) |
retryable_status_codes |
set[int] | None
|
Set of HTTP status codes to retry (for middleware) |
Functions¶
__str__
¶
Human-readable string representation.
calculate_delay
¶
Calculate delay for a given attempt number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attempt
|
int
|
Attempt number (1-based) |
required |
Returns:
| Type | Description |
|---|---|
float
|
Delay in seconds |
Source code in provide/foundation/resilience/retry.py
should_retry
¶
Determine if an error should be retried.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
error
|
Exception
|
The exception that occurred |
required |
attempt
|
int
|
Current attempt number (1-based) |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if should retry, False otherwise |
Source code in provide/foundation/resilience/retry.py
should_retry_response
¶
Check if HTTP response should be retried.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Any
|
Response object with status attribute |
required |
attempt
|
int
|
Current attempt number (1-based) |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if should retry, False otherwise |
Source code in provide/foundation/resilience/retry.py
SyncCircuitBreaker
¶
SyncCircuitBreaker(
failure_threshold: int = 5,
recovery_timeout: float = 30.0,
expected_exception: (
type[Exception] | tuple[type[Exception], ...]
) = Exception,
time_source: Callable[[], float] | None = None,
)
Synchronous circuit breaker for resilience patterns.
Uses threading.RLock for thread-safe state management in synchronous code. For async code, use AsyncCircuitBreaker instead.
Initialize the synchronous circuit breaker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
failure_threshold
|
int
|
Number of failures before opening circuit |
5
|
recovery_timeout
|
float
|
Seconds to wait before attempting recovery |
30.0
|
expected_exception
|
type[Exception] | tuple[type[Exception], ...]
|
Exception type(s) to catch |
Exception
|
time_source
|
Callable[[], float] | None
|
Optional callable that returns current time (for testing). Defaults to time.time() for production use. |
None
|
Source code in provide/foundation/resilience/circuit_sync.py
Functions¶
call
¶
Execute a synchronous function through the circuit breaker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable
|
Callable to execute |
required |
*args
|
Any
|
Positional arguments for func |
()
|
**kwargs
|
Any
|
Keyword arguments for func |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
Result from func |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If circuit is open |
Exception
|
Whatever exception func raises |
Source code in provide/foundation/resilience/circuit_sync.py
failure_count
¶
reset
¶
Reset the circuit breaker to its initial state.
state
¶
Get the current state of the circuit breaker.
Source code in provide/foundation/resilience/circuit_sync.py
Functions¶
circuit_breaker
¶
circuit_breaker(
failure_threshold: int = 5,
recovery_timeout: float = DEFAULT_CIRCUIT_BREAKER_RECOVERY_TIMEOUT,
expected_exception: (
type[Exception] | tuple[type[Exception], ...]
) = Exception,
time_source: Callable[[], float] | None = None,
registry: Registry | None = None,
) -> Callable[[F], F]
Create a circuit breaker decorator.
Creates a SyncCircuitBreaker for synchronous functions and an AsyncCircuitBreaker for asynchronous functions to avoid locking issues.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
failure_threshold
|
int
|
Number of failures before opening circuit. |
5
|
recovery_timeout
|
float
|
Seconds to wait before attempting recovery. |
DEFAULT_CIRCUIT_BREAKER_RECOVERY_TIMEOUT
|
expected_exception
|
type[Exception] | tuple[type[Exception], ...]
|
Exception type(s) that trigger the breaker. Can be a single exception type or a tuple of exception types. |
Exception
|
time_source
|
Callable[[], float] | None
|
Optional callable that returns current time (for testing). |
None
|
registry
|
Registry | None
|
Optional registry to register the breaker with (for DI). |
None
|
Returns:
| Type | Description |
|---|---|
Callable[[F], F]
|
Circuit breaker decorator. |
Examples:
>>> @circuit_breaker(failure_threshold=3, recovery_timeout=30)
... def unreliable_service():
... return external_api_call()
>>> @circuit_breaker(expected_exception=(ValueError, TypeError))
... async def async_unreliable_service():
... return await async_api_call()
Source code in provide/foundation/resilience/decorators.py
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | |