Skip to content

feat(net): Retry resilience layer (Slice 1, PR 3)#82

Merged
NotAProfDev merged 8 commits into
mainfrom
feat/net-http-retry
Jul 4, 2026
Merged

feat(net): Retry resilience layer (Slice 1, PR 3)#82
NotAProfDev merged 8 commits into
mainfrom
feat/net-http-retry

Conversation

@NotAProfDev

@NotAProfDev NotAProfDev commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Closes #81

Slice 1 PR 3 of the net-http resilience layers (spec: docs/superpowers/specs/2026-07-04-net-http-retry-layer-design.md; ADR-0031 §2). Builds on RateLimit (#76) and Timeout (#78).

  • Retry<S, T> + RetryLayer<T> (net-api::Layer) — order-safe retry: re-issues an explicitly-eligible request (a Retryable marker; absent → never retried, so a forgotten stamp never duplicates a POST) on a transient failure (HttpError::{Timeout, Connection}) or a 5xx response, with capped-exponential full-jitter backoff up to max_attempts.
  • Never retries a 429 / other 4xx / Auth / Throttled (ADR-0031 §2/§5); returns the last outcome verbatim on exhaustion.
  • Body-transparent — drops a superseded response, releasing its Guarded permit; Auth/RateLimit re-run per attempt (they sit inside Retry).
  • Explicit-only eligibility tightens ADR-0031 §2 (idempotent-method default → fail-safe opt-in), recorded as ADR-0034 Amendment feat: add just task runner, remove .cargo/config.toml #8.

Runtime-neutral: generic over net-api::Timer, jitter via an internal seeded SplitMix64no rand, no new dependency, no injected Jitter generic. MockTimer-driven tests with inline service doubles (+ the production Guarded for the permit-release test).

Next: Slice 1 PR 4 — the CircuitBreaker layer.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a net-http Retry resilience layer for explicitly eligible requests (opt-in retry marker).
    • Retries on transient transport failures and 5xx responses with capped exponential full-jitter backoff (configurable max attempts, base, cap, seed).
    • Never retries 429, other 4xx, or terminal auth/throttling/other failures; superseded responses are dropped to release any held permits, and exhaustion returns the last outcome as-is.
  • Documentation

    • Updated the changelog and added/expanded ADR/spec/plan docs covering configuration and semantics.
  • Tests

    • Added tests for eligibility gating, retry/non-retry rules, exhaustion behavior, jitter/backoff boundaries, and permit-release between attempts.

NotAProfDev and others added 6 commits July 4, 2026 17:50
Explicit-only Retryable eligibility (tightens ADR-0031 §2), transient-error
+ 5xx trigger set with no-retry-429, capped-exponential full-jitter backoff
via an internal seeded SplitMix64 (no rand dep, no Jitter generic), body-
transparent, attempts+backoff budget. MockTimer + inline-double testing.
Lands as ADR-0034 amendment #8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds RetryLayer<T> + Retry<S, T>: re-issues an eligible request on a
transient error (Timeout/Connection) or a 5xx response, with
capped-exponential full-jitter backoff, via the crate's SplitMix64
PRNG (Task 2). Body-transparent; drops the superseded response
(releasing any Guarded permit) before backing off.
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ec8d6f8e-c464-4392-8727-14b77fcaefe5

📥 Commits

Reviewing files that changed from the base of the PR and between cdeacce and a4e3c00.

📒 Files selected for processing (2)
  • crates/adapter/net/http/api/src/retry.rs
  • docs/superpowers/plans/2026-07-04-net-http-retry-layer.md
✅ Files skipped from review due to trivial changes (1)
  • docs/superpowers/plans/2026-07-04-net-http-retry-layer.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/adapter/net/http/api/src/retry.rs

📝 Walkthrough

Walkthrough

This PR adds a Retry resilience layer to the net-http adapter crate, including an opt-in request marker, retry configuration, jitter backoff, service wiring, and supporting ADR, changelog, and design/plan documentation.

Changes

Retry Layer Implementation

Layer / File(s) Summary
ADR amendment, changelog, and design/plan documentation
docs/adr/0034-http-construction-surface-auth-guarded-boot-coverage.md, CHANGELOG.md, docs/superpowers/plans/2026-07-04-net-http-retry-layer.md, docs/superpowers/specs/2026-07-04-net-http-retry-layer-design.md
Adds Retry semantics to the ADR, records the new changelog entry, and adds the implementation plan and design specification documents.
Retryable marker, RetryConfig, and module wiring
crates/adapter/net/http/api/src/retry.rs, crates/adapter/net/http/api/src/lib.rs
Defines the Retryable marker and RetryConfig, then exposes the new retry module and public re-exports from the crate root.
Retry service implementation and tests
crates/adapter/net/http/api/src/retry.rs
Adds RetryLayer and Retry, with transient and 5xx retry rules, non-retry outcomes, backoff timing, permit-dropping behavior, and async coverage tests.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related issues

Possibly related PRs

  • NotAProfDev/oath#58: Introduces the Service/Timer contract this retry layer builds on.
  • NotAProfDev/oath#66: Establishes the guarded-response permit semantics that this retry layer preserves by dropping superseded outcomes.

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title follows Conventional Commits and clearly summarizes the retry resilience layer change.
Linked Issues check ✅ Passed The changes align with #81 by adding Retry/RetryLayer, Retryable gating, transient and 5xx retries, capped jitter, and verbatim exhaustion handling.
Out of Scope Changes check ✅ Passed No unrelated scope is evident; the docs, changelog, and boundary fix all support the retry layer work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/net-http-retry

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/plans/2026-07-04-net-http-retry-layer.md`:
- Around line 309-320: The full-jitter helper in `duration_in` has an off-by-one
edge when the ceiling reaches `u64::MAX`, because the current `checked_add(1)`
path drops the inclusive upper bound. Update `duration_in(&self, ceil:
Duration)` to use a wider `u128` modulus (or equivalent wider arithmetic) when
sampling so the result remains uniformly inclusive over `[0, ceil]` even at the
maximum ceiling, while still preserving the existing zero-ceil fast path and
`Duration::from_nanos` conversion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7453b13e-6261-49d3-b231-0498c1683f96

📥 Commits

Reviewing files that changed from the base of the PR and between de2e5e4 and 1bd89b5.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • crates/adapter/net/http/api/src/lib.rs
  • crates/adapter/net/http/api/src/retry.rs
  • docs/adr/0034-http-construction-surface-auth-guarded-boot-coverage.md
  • docs/superpowers/plans/2026-07-04-net-http-retry-layer.md
  • docs/superpowers/specs/2026-07-04-net-http-retry-layer-design.md

Comment thread docs/superpowers/plans/2026-07-04-net-http-retry-layer.md Outdated
NotAProfDev and others added 2 commits July 4, 2026 18:48
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CodeRabbit (PR #82): duration_in's saturating_add(1) modulus dropped the
inclusive top value at ceil_nanos == u64::MAX (a ~584-year cap). Sample now
uses checked_add(1).map_or_else(full-u64-draw, % (n+1)), so [0, ceil] is
inclusive for every representable ceiling and the u64::MAX edge falls back to
the bare u64 draw (already uniform over [0, u64::MAX]). Adds a regression test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NotAProfDev NotAProfDev merged commit 68d8f60 into main Jul 4, 2026
4 checks passed
@NotAProfDev NotAProfDev deleted the feat/net-http-retry branch July 4, 2026 19:01
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.

feat(net): Retry resilience layer (Slice 1, PR 3)

1 participant