This page is an index of the public API: signatures and one-line purposes, with
links to the guides for behavior. Durations are always in seconds.
Public, and covered by the stability policy:
- every name in
relprim.__all__, imported from the top-level relprim package;
- every name in
__all__ of the optional modules relprim.opentelemetry,
relprim.jsonschema and relprim.pydantic;
- their documented parameters, attributes, methods and properties;
- documented runtime behavior, including the
event and metadata contract.
Not public:
- names starting with an underscore, including
AsyncOperation’s dataclass
fields and modules such as relprim._checks;
- the submodule where a core name is defined (
relprim.retry,
relprim.operation, …): import core names from relprim;
- module-level names not in
__all__;
- exception message text,
repr() output and validation reason wording;
- the
dev extra.
| Name |
Purpose |
resilient(...) |
Decorate an async def so calling it runs an operation and returns OperationResult[R]. All options are keyword-only. |
ResilientDecorator[RF] |
The protocol resilient(...) returns, for annotating a decorator stored in a variable. |
The decorated function keeps its parameters and returns
Coroutine[Any, Any, OperationResult[R]], or OperationResult[R | RF] with a
fallback returning RF. name defaults to the function’s __name__.
Each simple option and its advanced counterpart are mutually exclusive.
| Simple option |
Advanced option |
Builder method |
Guide |
retries, retry_on |
retry=RetryPolicy(...) |
with_retry |
Retry |
timeout=<seconds> |
timeout=TimeoutPolicy(...) |
with_timeout |
Timeouts |
fallback=<callable> |
fallbacks=fallback_chain(...) |
with_fallbacks |
Fallbacks |
| (none) |
circuit_breaker=CircuitBreaker(...) |
with_circuit_breaker |
Circuit breakers |
| (none) |
validation=validation_policy(...) |
with_validation |
Validation |
| (none) |
events=EventEmitter(...) |
with_events |
Structured events |
idempotency_key, idempotency_store, idempotency_ttl |
idempotency=idempotency_policy(...) |
with_idempotency |
Idempotency |
rate_limit_on, retry_after, max_rate_limit_wait |
rate_limit=RateLimitPolicy(...) |
with_rate_limit |
Rate limits |
retries=N equals RetryPolicy(max_attempts=N + 1); retries=0 disables
retrying.
retry_on defaults to (Exception,) and requires retries.
- Invalid or conflicting options raise
ValueError or TypeError when
resilient(...) is called.
- The decorator does not statically check that
validation, fallback or
idempotency_key match the function; the builder does.
| Name |
Purpose |
async_operation(name, operation) |
Create an AsyncOperation[P, R] from a name and an async callable. |
AsyncOperation |
Immutable operation configuration. Create it with async_operation, not its constructor. |
.with_retry(policy), .with_timeout(policy), .with_fallbacks(chain), .with_circuit_breaker(breaker), .with_validation(policy), .with_events(emitter), .with_idempotency(policy), .with_rate_limit(policy) |
Return a new operation with that policy set. Calling a method twice keeps the last policy. |
await .run(*args, **kwargs) |
Execute; return OperationResult[R] or raise OperationExecutionError. |
The order of builder calls never changes behavior; see
execution order.
| Signature |
Notes |
RetryPolicy(max_attempts=3, backoff=ExponentialBackoff(), retry_on=(Exception,), sleeper=time.sleep, async_sleeper=asyncio.sleep) |
max_attempts includes the first attempt. retry_on takes Exception subclasses only. |
RetryPolicy.run(operation, *args, **kwargs), await RetryPolicy.run_async(...) |
Standalone use; raise RetryError after the final attempt. |
ExponentialBackoff(base_delay_seconds=0.1, max_delay_seconds=10.0, multiplier=2.0, jitter=True) |
delay_for_retry(n), 1-based. With jitter, uniform in [0, computed]. |
| Signature |
Notes |
TimeoutPolicy(seconds) |
Async only. Raises OperationTimeoutError only when its own deadline expires. |
| Signature |
Notes |
fallback_chain(("name", operation), ..., policy=None) |
Create a FallbackChain. Same as FallbackChain.from_operations(...). |
FallbackChain(candidates, policy=FallbackPolicy()), FallbackCandidate(name, operation) |
Ordered candidates. await chain.run(*args) returns a FallbackResult. |
FallbackPolicy(fallback_on=(Exception,)) |
Which failures trigger a fallback, for the primary failure and between candidates. |
FallbackResult |
value, candidate_name, candidate_index, fallback_used, failures, failure_count. |
| Signature |
Notes |
CircuitBreaker(name="default", failure_threshold=5, recovery_timeout_seconds=30.0, record_failure_on=(Exception,), clock=time.monotonic) |
Shared, stateful; compares by identity. |
await breaker.run_async(operation, *args), await breaker.snapshot(), await breaker.reset() |
|
CircuitBreakerState |
closed, open, half_open. |
CircuitBreakerSnapshot |
Immutable: state, failure_count, opened_at, half_open_probe_in_flight, … |
| Signature |
Notes |
Validator[T] |
Protocol: read-only name, validate(value) -> ValidationResult. Contravariant. |
validator(name, predicate, *, message) → CallableValidator |
Dependency-free validator from a predicate. |
validation_policy(*validators) → ValidationPolicy |
Fail-fast, in order. Contravariant. |
ValidationPolicy.validate(value), .validate_or_raise(value) |
First failing result, or the last validator’s success result. validate_or_raise raises ValidationFailedError. |
ValidationResult(valid, validator_name, reason=None) |
ValidationResult.success(...), ValidationResult.failure(...), to_dict(). |
relprim.jsonschema.json_schema_validator(schema, *, name="json_schema") → JSONSchemaValidator |
JSON Schema. |
relprim.pydantic.pydantic_validator(model, *, name=None, strict=None) → PydanticValidator |
Pydantic. |
| Signature |
Notes |
idempotency_policy(key_factory, *, store=None, ttl_seconds=3600.0) → IdempotencyPolicy |
store=None creates an InMemoryIdempotencyStore. |
IdempotencyStore |
Protocol for custom stores. |
InMemoryIdempotencyStore(clock=time.monotonic) |
One process, one event loop. await purge_expired(), await entry_count(). |
IdempotencyResult, IdempotencyStatus |
executed, joined, replayed. |
| Signature |
Notes |
RateLimitPolicy(rate_limit_on, retry_after=None, max_wait_seconds=60.0) |
Also rate_limit_policy(...) with keyword arguments. |
RetryAfterExtractor |
Callable[[Exception], float | None]. |
RateLimitDecision |
Result of RateLimitPolicy.evaluate(exception): rate_limited, retry_after_seconds. |
| Signature |
Notes |
EventType |
Stable event identifiers. See event types. |
StructuredEvent(event_type, operation_name, timestamp, payload={}) |
Immutable; timezone-aware timestamp; JSON-scalar payload. to_dict(). |
EventEmitter(sinks=(NoopEventSink(),), timestamp_factory=...) |
Awaits sinks in order. |
EventSink |
Protocol: async emit(event). |
NoopEventSink(), InMemoryEventSink() |
await InMemoryEventSink.events(), .clear(). |
SQLiteEventStore(database, busy_timeout_seconds=5.0), StoredEvent |
SQLite event store. |
relprim.opentelemetry.OpenTelemetryEventSink() |
OpenTelemetry. |
| Name |
Members |
OperationResult[T] |
value, report, succeeded, failed. Returned for successful executions only. Covariant. |
ExecutionReport |
operation_name, status, started_at, duration_seconds, attempts, metadata, attempt_count, retry_count, retried, last_attempt, last_error, succeeded, failed, to_dict(). |
ExecutionAttempt |
attempt_number, status, started_at, duration_seconds, error, metadata, fallback, succeeded, failed, to_dict(). |
ExecutionError |
Serializable error summary: type, message, module, retryable, to_dict(). |
ExecutionStatus, AttemptStatus |
succeeded, failed, timed_out. |
attempt_count includes the fallback attempt; retry_count counts primary
attempts after the first one only.
Exception
└── RelPrimError
├── OperationExecutionError .report, .cause
├── RetryError .attempts, .cause
├── OperationTimeoutError .timeout_seconds, .cause
├── FallbackChainError .failures, .cause
├── CircuitBreakerOpenError .breaker_name, .state, .retry_after_seconds
├── ValidationFailedError .validator_name, .reason
├── RetryAfterExtractionError .rate_limit_error, .cause
├── IdempotencyReentryError .key
└── SQLiteEventStoreSchemaError
What AsyncOperation.run() and decorated functions raise:
| Situation |
Exception |
| The operation failed after retries and fallbacks |
OperationExecutionError; .cause is the final failure, for example OperationTimeoutError, ValidationFailedError, CircuitBreakerOpenError, FallbackChainError or the operation’s own exception |
| The calling task was cancelled |
asyncio.CancelledError, never wrapped |
| An event sink raised |
The sink’s exception, unchanged |
| The idempotency key factory raised or returned a bad key |
The original exception, or TypeError / ValueError |
| The same idempotency key was reused recursively |
IdempotencyReentryError |
Configuration mistakes raise ValueError or TypeError when a policy is
constructed or resilient(...) is called. Optional integrations let
third-party configuration errors through unchanged, such as
jsonschema.exceptions.SchemaError, and SQLiteEventStore propagates sqlite3
errors unchanged. RetryError is raised only by the standalone
RetryPolicy.run* methods.