Skip to content

Add RetryConfig record for RetryMiddleware#150

Merged
chris-colinsky merged 2 commits into
mainfrom
feature/0050-retry-config
Jun 11, 2026
Merged

Add RetryConfig record for RetryMiddleware#150
chris-colinsky merged 2 commits into
mainfrom
feature/0050-retry-config

Conversation

@chris-colinsky

Copy link
Copy Markdown
Member

Second PR in the proposal 0050 series (after #149 / FailureIsolationMiddleware). This is a pure refactor that prepares for call-level retry by making RetryMiddleware consume a shared RetryConfig record. The call-level retry feature itself (complete(retry=...) + the in-call loop) follows in a third PR.

What

RetryMiddleware's individual constructor kwargs are replaced by a single frozen RetryConfig (max_attempts / classifier / backoff / on_retry). Construct as RetryMiddleware(RetryConfig(max_attempts=...)); bare RetryMiddleware() still applies the defaults.

This is the same record the upcoming call-level complete(retry=...) parameter will accept, so a caller writes one retry config and uses it at either the per-node or the per-call layer.

The config fields are Optional and resolve to the canonical defaults (default_classifier / exponential_jitter_backoff) once in the consumer, preserving the prior None-means-default behavior. That keeps fixture-driven construction in the conformance harness robust (it passes None for unspecified settings) and makes every call-site migration a uniform RetryMiddleware(RetryConfig(...)) wrap.

Breaking change

The RetryMiddleware(max_attempts=..., ...) kwargs constructor is removed. All call sites across the repo (tests, examples, docs) are migrated in this PR. No back-compat shim, by design.

Scope

  • No spec-pin change: proposal 0050 is already within the current v0.53.0 pin.
  • The conformance harness directive schema (directives.py) is untouched: its RetryMiddleware is a Pydantic YAML model, not the real constructor; the real middleware is built in the migrated test bodies.

Tests

Two new RetryConfig tests (validation, default resolution) plus the migrated existing retry coverage. Full suite green (1261 passed), pyright and ruff clean, docs build clean.

Replace RetryMiddleware's individual constructor kwargs with a single
frozen RetryConfig (max_attempts / classifier / backoff / on_retry),
constructed as RetryMiddleware(RetryConfig(...)). This is the shared
record the upcoming call-level complete(retry=...) parameter will take,
so one config serves both the per-node and per-call retry layers.

The config fields are Optional and resolve to the canonical defaults
(default_classifier / exponential_jitter_backoff) once in the consumer,
preserving the prior None-means-default behavior so fixture-driven
construction stays robust.

Breaking change to the RetryMiddleware constructor; all call sites
across tests, examples, and docs are migrated. First of two refactor
PRs splitting proposal 0050's remaining work; call-level retry follows.
Copilot AI review requested due to automatic review settings June 10, 2026 23:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors RetryMiddleware to consume a shared immutable RetryConfig record, aligning per-node retry configuration with the upcoming call-level retry API and migrating all internal call sites accordingly.

Changes:

  • Introduces RetryConfig (frozen dataclass) and updates RetryMiddleware to accept it (or default to RetryConfig()).
  • Migrates usages across tests, conformance harness builders, examples, and docs to RetryMiddleware(RetryConfig(...)).
  • Updates public re-exports and changelog to reflect the breaking constructor change.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/unit/test_observability_otel.py Updates retry middleware construction to use RetryConfig.
tests/unit/test_observability_metadata.py Updates retry middleware construction to use RetryConfig.
tests/unit/test_middleware.py Migrates retry tests and adds basic RetryConfig validation/default tests.
tests/unit/test_fan_out.py Updates retry middleware construction to use RetryConfig.
tests/unit/test_failure_isolation_middleware.py Updates composed middleware example to use RetryConfig.
tests/conformance/test_pipeline_utilities.py Updates middleware factory to build RetryConfig for RetryMiddleware.
tests/conformance/test_observability.py Updates fixture-driven retry middleware creation to use RetryConfig.
src/openarmature/graph/middleware/retry.py Adds RetryConfig and refactors RetryMiddleware to consume it.
src/openarmature/graph/middleware/init.py Re-exports RetryConfig from openarmature.graph.middleware.
src/openarmature/graph/init.py Re-exports RetryConfig from openarmature.graph.
examples/parallel-branches/main.py Updates example to use RetryMiddleware(RetryConfig(...)).
examples/fan-out-with-retry/main.py Updates example to use RetryMiddleware(RetryConfig(...)).
docs/concepts/middleware.md Updates documentation examples and wording for RetryConfig.
CHANGELOG.md Documents the breaking RetryMiddleware constructor change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/openarmature/graph/middleware/retry.py Outdated
From CoPilot review of PR #150: RetryMiddleware now takes a positional
config, so a non-RetryConfig argument (e.g. RetryMiddleware(3)) would
construct and then fail with a cryptic AttributeError at retry time.
Raise TypeError eagerly in __init__ with the correct-usage idiom, and
add a test.
@chris-colinsky chris-colinsky merged commit 8dde25a into main Jun 11, 2026
6 checks passed
@chris-colinsky chris-colinsky deleted the feature/0050-retry-config branch June 11, 2026 00:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants