Skip to main content

Banner

flexinfer-resilience

Header

pipeline status coverage report

Production-ready resilience patterns for Python applications.

Features

  • Circuit Breaker - Prevents cascading failures by failing fast when services are down
  • Rate Limiter - Token bucket rate limiting with exponential backoff
  • Retry - Automatic retries with configurable backoff strategies (constant, linear, exponential, decorrelated jitter)
  • Bulkhead - Concurrency isolation using semaphores to prevent resource overload
  • Timeout - Time-bounded operations with fallback support
  • Async-first - Built for asyncio with full async/await support
  • Type hints - Complete type annotations for IDE support
  • Zero dependencies - Uses only Python standard library (optional Redis support)
  • Distributed State - RedisCircuitBreaker for sharing circuit state across multiple instances.

Installation

pip install flexinfer-resilience

Import path stays resilience:

from resilience import CircuitBreaker

Or install from GitLab:

pip install git+https://gitlab.flexinfer.ai/libs/py-resilience.git

Quick Start

Circuit Breaker

from resilience import CircuitBreaker, CircuitBreakerConfig

# Create a circuit breaker with custom config
config = CircuitBreakerConfig(
    failure_threshold=5,      # Open after 5 failures
    recovery_timeout=30.0,    # Wait 30s before half-open
    success_threshold=2,      # Close after 2 successes in half-open
)
breaker = CircuitBreaker("my-api", config)

# Use as context manager
async def call_api():
    async with breaker:
        return await external_api.fetch()

# Or use execute method
result = await breaker.execute(external_api.fetch)

# Or use as decorator
@breaker.decorate
async def decorated_call():
    return await external_api.fetch()

Rate Limiter

from resilience import RateLimiter, RateLimitConfig

# Create a rate limiter
config = RateLimitConfig(
    requests_per_second=10,   # 10 requests per second
    burst_size=20,            # Allow bursts up to 20
)
limiter = RateLimiter(config)

# Acquire a token before making requests
async def rate_limited_call():
    await limiter.acquire()
    return await api.request()

# Or check without blocking
if await limiter.try_acquire():
    await api.request()
else:
    print("Rate limited, try again later")

Combined Usage with Retry

from resilience import (
    CircuitBreaker,
    RateLimiter,
    execute_with_retry,
    CircuitBreakerOpenError,
)

limiter = RateLimiter(RateLimitConfig(requests_per_second=5))

# Execute with automatic retry and rate limiting
result = await execute_with_retry(
    fetch_data,
    url="https://api.example.com",
    rate_limiter=limiter,
    max_retries=3,
    retry_exceptions=(TimeoutError, ConnectionError),
)

API Reference

CircuitBreaker

class CircuitBreaker:
    def __init__(self, name: str, config: CircuitBreakerConfig | None = None): ...

    @property
    def state(self) -> CircuitState: ...  # CLOSED, OPEN, or HALF_OPEN

    async def execute(self, func, *args, **kwargs) -> T: ...
    async def __aenter__(self) -> CircuitBreaker: ...
    async def __aexit__(self, ...): ...
    def decorate(self, func) -> func: ...
    def reset(self) -> None: ...

CircuitBreakerConfig

Parameter Type Default Description
failure_threshold int 5 Failures before opening
recovery_timeout float 30.0 Seconds before half-open
half_open_max_calls int 3 Test calls in half-open
success_threshold int 2 Successes to close
excluded_exceptions tuple () Exceptions that don't count as failures

RateLimiter

class RateLimiter:
    def __init__(self, config: RateLimitConfig | None = None): ...

    async def acquire(self, tokens: int = 1) -> float: ...  # Returns wait time
    async def try_acquire(self, tokens: int = 1) -> bool: ...
    def backoff_delay(self, attempt: int) -> float: ...
    def reset(self) -> None: ...

RateLimitConfig

Parameter Type Default Description
requests_per_second float 10.0 Target request rate
burst_size int 2x rate Maximum burst allowed
max_retries int 5 Retry attempts
base_delay float 1.0 Initial backoff delay
max_delay float 60.0 Maximum backoff delay
jitter bool True Add random jitter

Registry Pattern

For managing multiple circuit breakers:

from resilience import CircuitBreakerRegistry

# Get or create circuit breakers by name (singleton)
registry = CircuitBreakerRegistry()
breaker = registry.get("api-service")

# Pre-configure breakers
registry.configure("api-service", CircuitBreakerConfig(failure_threshold=3))

# Get stats for all breakers
stats = registry.get_stats()

Circuit Breaker States

     ┌─────────────────────────────────────────┐
     │                                         │
     ▼                                         │
┌─────────┐  failure_threshold   ┌──────────┐  │
│ CLOSED  │ ──────────────────▶  │   OPEN   │  │
└─────────┘                      └──────────┘  │
     ▲                                │        │
     │                                │ recovery_timeout
     │ success_threshold              ▼        │
     │                          ┌───────────┐  │
     └───────────────────────── │ HALF_OPEN │──┘
                                └───────────┘ failure
  • CLOSED: Normal operation, requests pass through
  • OPEN: Service failing, requests rejected immediately
  • HALF_OPEN: Testing recovery with limited requests

License

MIT License - see LICENSE

Metadata

Release files for flexinfer-resilience 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for flexinfer-resilience 0.2.2
File Interpreter ABI Platform
flexinfer_resilience-0.2.2-py3-none-any.whl Python 3 none any Details

Release files / flexinfer_resilience-0.2.2-py3-none-any.whl

Download URL flexinfer_resilience-0.2.2-py3-none-any.whl
Size 21.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fa93885f0223858d773cbd3e06e7c2b3bb1d02c8d9a5dffd839420f138a53d4d
BLAKE2b-256 checksum
How to use checksums
b60625dfe2be6763784f2e1c8089cc3eace909f5c21d347df182bf755675cd55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.12

Security for flexinfer-resilience 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.2 This release

1 release file No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page