Skip to content

Tracking: retry/backoff policy — Retry-After cap + live-task bound #220

Description

@erskingardner

Root cause

Retry policy decisions are scattered across retry.rs constants, header parsing, and permit mechanics, and two of them break the system's own stated invariants under provider stress:

Refactor design

On top of the push-provider tracker's rewritten retry engine (hard dependency — same retry.rs machinery):

  1. Cap honored Retry-After at a small policy ceiling (e.g. 60–120s): server_delay.min(MAX_RETRY_AFTER) in retry_wait_duration/parse_retry_after ([LOW] Provider-supplied Retry-After is honored verbatim with no upper bound — an untrusted header can pin a send task (and its decrypted token) for an arbitrary duration #162).
  2. Bound total live tasks (active + sleeping-in-backoff) independently of active-HTTP concurrency: a second semaphore gating task spawn/dequeue, or a cap on how many tasks may hold a released permit at once — so backoff can no longer balloon live decrypted-token residency to queue size ([MEDIUM] Backoff permit release lets live send-task (and decrypted-token) count exceed the 100 concurrency bound up to the full 10k queue #160).
  3. Carry forward PR fix: desynchronize push retry backoff #204's floor + jitter as first-class policy in the new engine (single RetryPolicy struct owning floor, cap, jitter, budget), so the lower bound ([LOW] Retry backoff has no minimum floor and no jitter: Retry-After: 0 yields immediate back-to-back retries and concurrent sends retry in synchronized waves #96), upper bound ([LOW] Provider-supplied Retry-After is honored verbatim with no upper bound — an untrusted header can pin a send task (and its decrypted token) for an arbitrary duration #162), and concurrency interaction ([MEDIUM] Backoff permit release lets live send-task (and decrypted-token) count exceed the 100 concurrency bound up to the full 10k queue #160) live in one reviewed place.

Members

In-flight PRs

Sequencing

Wave 2 — hard-blocked behind the push-provider tracker (both rewrite with_retry/BackoffPermit in retry.rs). The optional dispatcher InFlightTrackerTaskTracker unification (from the lifecycle tracker) also waits for this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions