struct

Arcana::AI::RetryPolicy

Inherits Struct < Value < Object

Retrying calls that failed for a reason that may pass: rate limits (429), server errors (500, 502, 503, 504, and Anthropic's 529 overloaded) and network errors.

  • Waits as long as the provider asks (Retry-After, retry-after-ms, or Gemini's retryDelay), up to max_wait; a longer requested wait fails at once rather than stalling the caller.
  • Otherwise backs off base_delay, doubling each time, capped at max_delay, with ±25% jitter so many clients don't retry in step.
  • Never retries what can't pass soon: OpenAI's insufficient_quota (a spending cap, sent as 429) or a per-day quota.
  • A network error is retried only before the response has started (see Attempt#started!): a stream that already sent events to the caller can't be replayed.

Constants

RETRY_STATUSES = {429, 500, 502, 503, 504, 529}

Constructors

new(max_retries : Int32 = 3, base_delay : Time::Span = 500.milliseconds, max_delay : Time::Span = 8.seconds, max_wait : Time::Span = 30.seconds)
Source
none

No retries: the first failure is raised.

Source

Class methods

retry_after(headers : HTTP::Headers, body : String) : Time::Span | Nil

The wait a failed response asks for, if it names one.

Source

Instance methods

backoff(retries : Int32) : Time::Span
Source
base_delay
Source
delay_for(ex : Exception, retries : Int32, attempt : Attempt = Attempt.new) : Time::Span | Nil

The wait before retrying after ex, or nil to give up.

Source
max_delay
Source
max_retries
Source
max_wait
Source
run(ctx : Context | Nil = nil, on_retry : Proc(Int32, Time::Span, String, Nil) | Nil = nil, & : Attempt -> T) : Tuple(T, RetryStats) forall T

Run the block (one try per call) until it returns, fails for good, or ctx is cancelled. on_retry hears of each retry before the wait: (retry number, delay, reason).

Source

Nested types