Skip to main content

retrying

Function retrying 

Source
pub fn retrying<T>(
    op: impl FnMut() -> TransportResult<T>,
    backoff: fn() -> BackoffIterator,
    sleep: fn(Duration),
) -> TransportResult<T>
Expand description

Transport-agnostic retry driver shared by every Transport implementation, so the SPEC-TRANSPORT §7 ladder lives in exactly one place instead of being reimplemented per crate. Extracted from what was HttpTransport::retrying in mkit-transport-http.

op is re-invoked from scratch on every attempt — it MUST perform a fresh, self-contained unit of work each call (a new HTTP request on the existing connection pool, a freshly-reconnected SSH child, a redialed encrypted session, …) rather than assuming any state left over from a failed prior attempt is still valid. This matters most for connection-oriented transports: a frame-level failure can leave a stream mid-message-desynced, so op reconnecting before retrying (rather than resuming on the same broken handle) is what makes the retry safe, not just present.

backoff is a ladder factory (not a live iterator) so a fresh ladder starts on every call to retrying — production uses BackoffIterator::new, tests inject a short/deterministic ladder. sleep is the delay hook between attempts; production sleeps for the full duration, tests typically inject a no-op or recorder.

Retries only the classes is_retryable accepts (ConnectionFailed, ServerError{5xx}, ServerError{429}); every other error returns immediately on the first attempt.