aws/retry

Retry middleware. Wraps any http_send.Send with the retry semantics the AWS Smithy runtime ships (aws-sdk-rust/…/client/retries/strategy/standard.rs).

Behaviour mirrored from upstream:

Deliberately out of scope (explicit deltas vs Rust SDK, documented for the M4 audit):

Types

What the strategy decided after looking at the last attempt.

pub type Decision {
  Stop
  RetryAfter(delay_ms: Int, cost: Int)
  GiveUp
}

Constructors

  • Stop

    Attempt succeeded — return the response to the caller.

  • RetryAfter(delay_ms: Int, cost: Int)

    Attempt failed retryably — sleep delay_ms then attempt again. cost is the number of tokens the bucket should debit before the retry.

  • GiveUp

    Attempt failed non-retryably or attempts are exhausted.

A retry strategy. Opaque to callers; build via standard / adaptive.

pub opaque type Strategy

Values

pub fn adaptive(bucket bucket: rate_limiter.Bucket) -> Strategy

Standard retry with a token-bucket gate. Equivalent to Rust SDK “adaptive” minus the CUBIC client rate limiter (see module docs).

pub fn adaptive_with(
  bucket bucket: rate_limiter.Bucket,
  max_attempts max_attempts: Int,
  base_delay_ms base_delay_ms: Int,
  max_delay_ms max_delay_ms: Int,
  sleep sleep: fn(Int) -> Nil,
  rng rng: fn() -> Float,
) -> Strategy
pub fn classify(
  result: Result(response.Response(BitArray), http_send.HttpError),
  attempt: Int,
  strategy: Strategy,
) -> Decision

Classify one attempt’s outcome. Exposed for test asserting and so the protocol-codec layer (M5) can override per-service error semantics.

pub const default_base_delay_ms: Int

Base delay before the first retry, in milliseconds.

pub const default_max_attempts: Int

Default maximum total attempts. Matches AWS SDK “standard” mode.

pub const default_max_delay_ms: Int

Cap on any individual retry delay, in milliseconds. Matches Rust SDK’s MAX_BACKOFF (20 s).

pub fn exponential_backoff(
  strategy: Strategy,
  attempt: Int,
) -> Int

Exponential backoff with full jitter, mirrored from Rust SDK calculate_exponential_backoff:

raw = base * 2^(attempt-1) bound = min(raw, max) delay = rng() * bound

attempt is 1-indexed (the first retry uses base * 2^0 = base).

pub const retry_cost: Int

Token cost for a normal retryable error (throttling, server fault, retryable client). Matches Rust SDK DEFAULT_RETRY_COST = 5.

pub fn standard() -> Strategy
pub fn standard_with(
  max_attempts max_attempts: Int,
  base_delay_ms base_delay_ms: Int,
  max_delay_ms max_delay_ms: Int,
  sleep sleep: fn(Int) -> Nil,
  rng rng: fn() -> Float,
) -> Strategy
pub const timeout_retry_cost: Int

Token cost for a transient / timeout retry. Matches Rust SDK DEFAULT_RETRY_TIMEOUT_COST = DEFAULT_RETRY_COST * 2 = 10.

pub fn with_base_delay_ms(
  strategy: Strategy,
  base_delay_ms: Int,
) -> Strategy

Override the initial-retry-backoff base on an existing Strategy. The first retry sleeps roughly base_delay_ms with full jitter; each subsequent attempt doubles the cap up to max_delay_ms. Set to 0 (paired with with_max_delay_ms(0)) for tests that want zero-delay retries.

pub fn with_max_attempts(
  strategy: Strategy,
  max_attempts: Int,
) -> Strategy

Override the per-request max attempt count on an existing Strategy, preserving the other knobs (delays, sleep / rng / rate-limiter). The common case for tuning retry behaviour — callers usually want the AWS-recommended backoff curve but a different attempt budget (1 for fail-fast tests, 5 for long-running batch workloads, etc.).

Strategy is opaque so this setter lives here; the runtime re-exports a with_max_attempts(config, n) convenience that threads through to this setter.

pub fn with_max_delay_ms(
  strategy: Strategy,
  max_delay_ms: Int,
) -> Strategy

Override the maximum-backoff cap on an existing Strategy. Pairs with with_base_delay_ms for tests that need zero or very short delays; production callers usually keep the AWS- recommended default.

pub fn with_retry(
  send send: fn(request.Request(BitArray)) -> Result(
    response.Response(BitArray),
    http_send.HttpError,
  ),
  strategy strategy: Strategy,
) -> fn(request.Request(BitArray)) -> Result(
  response.Response(BitArray),
  http_send.HttpError,
)

Wrap a Send with retry semantics.

Search Document