A stability release

RelPrim 1.0.0 is the first stable release.

The pre-stable releases built the primitives one at a time: retries, timeouts, fallbacks, circuit breakers, validation, idempotency, rate-limit recovery, OpenTelemetry and SQLite events, and JSON Schema and Pydantic adapters. Version 1.0 adds no new primitive. It fixes the behavior of the existing ones, writes that behavior down, and promises to keep it.

From 1.0.0 on, RelPrim follows Semantic Versioning. The stability policy defines what that covers.

A defined public API

Every public name is now listed in the API reference, grouped by domain. Names that are not listed there, and anything starting with an underscore, are internal.

A few names that RelPrim never actually produced were removed before the freeze, including RetryAttempt and the unused CANCELLED statuses, so the stable surface only contains what the library really does.

Typing that holds up under strict checking

The package now ships a py.typed marker (PEP 561), so type checkers use RelPrim’s own annotations instead of treating it as untyped.

@resilient(...) now preserves the decorated function’s parameters and types its result as OperationResult[R], or OperationResult[R | RF] when a fallback returns RF. In 0.11, most configurations were rejected by strict type checkers, so casts and # type: ignore comments added as workarounds can now be removed.

Semantics that match their names

The hardening work fixed behavior where the result surprised the caller:

  • Cancellation is never retried, never falls back and is never recorded as a circuit-breaker failure. A cancelled half-open probe releases the breaker instead of blocking it.
  • Timeouts raise OperationTimeoutError only when the policy’s own deadline expires. A client’s own TimeoutError is reported as the failure it is.
  • Fallbacks validate each candidate’s result, so an invalid backup response is a failed candidate. FallbackPolicy now also decides whether the primary failure falls back at all.
  • Retry counts describe the primary path only; a fallback attempt is marked as such and is no longer counted as a retry.
  • Configuration that used to be silently ignored, such as retry_on without retries, is now rejected.

Idempotency, stated precisely

Idempotency coordinates duplicate calls and replays successful results. The 1.0 documentation is explicit that this is not an exactly-once guarantee for external side effects, and explains how to combine it with a provider’s own idempotency key. Raw keys are also no longer copied into report metadata.

A stable event and metadata contract

Event types, their payload keys and the execution report metadata keys are now documented in one place, in structured events. They are part of the stable API: minor releases may add keys, but do not rename or remove them. The OpenTelemetry attribute names and the SQLite event-store schema follow the same rule.

Supported Python and verified packages

RelPrim 1.0 supports Python 3.11–3.14. CI tests every supported version, and also installs the built wheel and source distribution in clean environments to check what is actually published.

Documentation

RelPrim now has full documentation: a getting started guide, a page for every primitive, the API reference and the stability policy. The documentation is versioned, so the 1.0 pages stay available as later releases ship.

Upgrading from 0.11

Most applications need no code changes. The migration guide lists every user-visible change and what to do about it. The changes most likely to matter are retry_on validation, per-candidate fallback validation and timeout reporting.

pip install --upgrade relprim