Skip to main content

resilient-result

PyPI version Python 3.8+ License: MIT

Resilience mechanisms with Result types.

from resilient_result import resilient, Result

# Simple: perfect defaults for most cases
@resilient()
async def call_api(url: str) -> str:
    return await http.get(url)

# Advanced: compose individual mechanisms
@timeout(seconds=10)
@retry(attempts=5)  
async def robust_call(url: str) -> str:
    return await http.get(url)

result: Result[str, Exception] = await call_api("https://api.example.com")
if result.success:
    data = result.unwrap()  # Extract data safely
    print(data)
else:
    print(f"Failed: {result.error}")  # Inspect error directly

Why resilient-result? Network calls fail. Databases timeout. APIs rate limit. Handle it cleanly without exception soup.

Observability built-in: Enable logging.getLogger('resilient_result').setLevel(logging.DEBUG) to see retry attempts and recovery.

📖 Result API | 🔧 Resilience Patterns

Installation

pip install resilient-result

Core Features

Progressive Disclosure

from resilient_result import resilient, retry, timeout, circuit, rate_limit

# Simple: Just works with reasonable defaults
@resilient()  # 2 attempts, 1s backoff, 30s timeout
async def simple_operation():
    return await external_service()

# Advanced: Compose individual mechanisms
@rate_limit(rps=100)         # Rate limiting (100 rps default)
@circuit(failures=3)         # Circuit breaker (1 minute window)
@timeout(seconds=10)         # Time-based protection
@retry(attempts=5)           # Retry mechanism
async def critical_operation():
    return await external_service()

Result Usage

from resilient_result import Result, Ok, Err

# Pattern 1: Check then unwrap
result = await call_api("https://api.example.com")
if result.success:
    data = result.unwrap()
    process(data)

# Pattern 2: Error inspection for conditional logic
result = await call_api("https://api.example.com")
if result.failure and "rate_limit" in result.error:
    await asyncio.sleep(60)  # Backoff on rate limit
    retry()
elif result.failure:
    log_error(result.error)

# Pattern 3: Direct unwrap (raises exception on failure)
try:
    data = result.unwrap()
    process(data)
except ApiError as e:
    log_error(e)

Policy Configuration

from resilient_result import Retry, Backoff, Circuit, resilient

# Explicit policy configuration
@resilient(
    retry=Retry(attempts=5, timeout=60),
    backoff=Backoff.exp(delay=0.1, max_delay=10),  # Jitter enabled by default
    circuit=Circuit(failures=3, window=60)  # 1 minute window
)
async def custom_operation():
    return await external_service()

# Shorthand for common patterns
@resilient(retry=Retry(attempts=5))  # Just more attempts
@resilient(timeout=60)               # Just longer timeout
async def database_operation():
    return await db.query()

Parallel Operations

from resilient_result import Result

# Collect multiple async operations
operations = [fetch_user(1), fetch_user(2), fetch_user(3)]
result = await Result.collect(operations)

if result.success:
    users = result.unwrap()  # All succeeded
else:
    try:
        result.unwrap()  # Raises first failure
    except Exception as e:
        print(f"First failure: {e}")

Error Inspection Patterns

# Canonical API: 3 ways to work with Results
result = await call_api("https://api.example.com")

# 1. Status checking
if result.success:
    print("Success!")
if result.failure:
    print("Failed!")

# 2. Error inspection (without exceptions)
if result.failure:
    error_msg = result.error
    if "network" in str(error_msg):
        retry_with_backoff()
    elif "auth" in str(error_msg):
        refresh_token()

# 3. Value extraction (raises on failure)
try:
    data = result.unwrap()  
    process(data)
except Exception as e:
    handle_error(e)

License

MIT - Build amazing resilient systems! 🚀


🗺️ Roadmap

Release files for resilient-result 0.4.1

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

Source distribution (sdist)

Source distribution for resilient-result 0.4.1
File Size Uploaded
resilient_result-0.4.1.tar.gz 10.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for resilient-result 0.4.1
File Interpreter ABI Platform
resilient_result-0.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 22.5 kB

Release files / resilient_result-0.4.1.tar.gz

Download URL resilient_result-0.4.1.tar.gz
Size 10.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6f7f3d8f1e513058790ba415ed519e82f81d1e4aa2ed4f32a16ee158ea3fa8c7
BLAKE2b-256 checksum
How to use checksums
68190dea2f5095d26aa6d4aa496d1945531893b7d8eaf9f2691ce410c0648376
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.12.10 Darwin/24.5.0

Release files / resilient_result-0.4.1-py3-none-any.whl

Download URL resilient_result-0.4.1-py3-none-any.whl
Size 12.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
31edb802ea60a313c7fbf15a501bc2aec023794a2b64ffa5e7424684687603df
BLAKE2b-256 checksum
How to use checksums
dcb0abf94b578d042ba11936c2239746c8ee835007e86e35b78f225cf09d0612
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.12.10 Darwin/24.5.0

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

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