Skip to content

Phase 6a: Retry #22

Description

@Wahbeh-Mohammad

Build the retry subsystem in full: one shared policy core (status-and-throwable classification, the
re-sendability gate, the backoff calculator, the pacing-header parser, tuning constants) and the two stacks
— the recovery-chain retry that installs beneath phase 4b's Recovery::Orchestrator with a total-timeout
budget, and the stage-based pillar step at Dexpace::Pipeline::Stages::RETRY with a sync and an async driver.
The largest sub-phase in the roadmap, sixty IDs.

Scope

  • Dexpace::Resilience::Policy (visibility and Resend.eligible?, R5): classification via RETRY-2's
    capability-only throwable query and its blind spot (R4), RETRY-13's single backoff calculator serving two
    budget policies (R6), Retry-After pacing through phase 5a's Dexpace::HTTPDate.parse against RETRY-15's
    tolerances (R1), idempotency-key preservation.
  • The recovery-stack engine — RECOV-17–RECOV-30 and RECOV-34, each with its own checklist row (a
    cross-reference to the RETRY twin is an annotation, never the row's disposition) — installing into what
    4b shipped, with CFG-15's cancellable wait as its delay primitive.
  • The pillar step at Stages::RETRY with a sync driver and an async trampoline that needs no Fiber.scheduler
    (R2); the retry step's HTTPTracer source (R3); per-attempt OBS-29 events — attempt started, attempt
    failed with next delay, retries exhausted (R15 decides no PRE_REDIRECT; phase 10 confirmed it).
  • Picks up and closes: ProtocolError#retryable_by_status?, CFG-35's throwable half, and the Cursor
    context-bundle widening (Task 8) that 6b and 6c consume if it exists and never wait on.

Spec refs

Product spec §9 — RETRY-1–RETRY-45 (45); appendix C — RECOV-17–RECOV-30, RECOV-34 (15, the largest
gap cluster in the corpus; budget the spec reading). sdk-design: §6.1, §8.3.

Dependencies

Phases 0–5 — and phase 5 is a real prerequisite: RETRY-12's defaults come from CFG-14, the delay from
CFG-15–CFG-21, the events from 5b/5c's instrumentation. Independent of 6b and 6c — 4c's
stage-namespaced cursor state makes a RETRY fork's state: invisible under any other stage's key, which is
the same assertion that keeps 6b/6c's marker exchange safe from 6a.

Docs

  • Segmentation: docs/work/mvp/phase6/2026-09-09-phase6-segmentation-design.md
  • Design: docs/work/mvp/phase6/phase6a/2026-09-09-phase6a-retry-design.md
  • Plan: docs/work/mvp/phase6/phase6a/2026-09-09-phase6a-retry.md (13 tasks)
  • Checklist: docs/work/mvp/phase6/phase6a/<date>-phase6a-retry-checklist.md — written at execution time, one
    row per ID in scope, sixty rows

Notes

Recommended first of the three for four reasons the charter gives: longest pole, closes or half-closes four
postponed items, owns the cursor widening, and touches neither side of the redirect-then-auth marker. RETRY-28
is a phase-10 row by design §10's closing note. RETRY-38 (MAY) is declined for v1 with RECOV-31.

Activity

  1. added this to the v1/mvp milestone on Sep 13, 2026
  2. added
    type:featureNew capability or enhancement
    area:coreCore HTTP, IO, body, context, encoding: HTTP-* IO-* BODY-* CTX-* UTF-*
    area:resilienceRetry, recovery, redirects: RETRY-* RECOV-* REDIR-*
    on Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:coreCore HTTP, IO, body, context, encoding: HTTP-* IO-* BODY-* CTX-* UTF-*area:resilienceRetry, recovery, redirects: RETRY-* RECOV-* REDIR-*type:featureNew capability or enhancement

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions