RequestInterceptors

public enum RequestInterceptors

Factories for the built-in RequestInterceptors that add retry behavior to a NetworkClient.

Pass the created interceptors to NetworkClient.newClient(withAdditionalInterceptors:maxRetryCount:). Interceptors are consulted in reverse order, so add retryWhenConnected(connectivityManager:) last: it is then asked first and, while the connection is assumed unavailable, waits for it instead of letting retryWithBackoff(...) use up its attempts:

let client = context.network.networkClient.newClient(withAdditionalInterceptors: [
    RequestInterceptors.retryWithBackoff(maxAttempts: 3),
    RequestInterceptors.retryWhenConnected(connectivityManager: context.network.connectivityManager)
], maxRetryCount: 10)
  • Creates a RequestInterceptor that makes a retryable failure wait for the SDK’s connectivity signal while the connection is assumed unavailable.

    For a retryable error while ConnectivityManagerProtocol.connectionAssumedAvailable is false, the interceptor retries the next time connectionAssumedAvailable becomes true. Otherwise it expresses no opinion, so another interceptor may still retry.

    Declaration

    Swift

    static func retryWhenConnected(connectivityManager: ConnectivityManagerProtocol) -> RequestInterceptor

    Parameters

    connectivityManager

    the connectivity manager used to know when connectivity is assumed available again.

    Return Value

    a new RequestInterceptor; it can be shared between clients.

  • Creates a RequestInterceptor that retries retryable failures with a full-jitter exponential backoff, and decides when to give up.

    • A failure is retryable when its NetworkErrorType.isRetryable is true, for example HTTP 429 and 503, or a lost connection.
    • The n-th retry in a row proposed by this interceptor, counting from 0, waits a random delay between 0 and min(maxDelay, base * 2^n). base is throttlingBaseDelay for HTTP 429 and transientBaseDelay otherwise.
    • A Retry-After header is a minimum wait: the delay is the larger of the header and the backoff. The header can be a number of seconds or an HTTP date in the IMF-fixdate format, measured against the response’s Date header when present so a skewed device clock doesn’t matter. Other formats are ignored. For a header above maxDelay, the interceptor either stops proposing a retry or waits for it in full, depending on retryAfterAboveMaxDelay.
    • maxAttempts counts consecutive attempts, including the one that just failed. The count, and with it the backoff, restarts when another interceptor proposed the last retry, for example after waiting for connectivity. To limit the total retries of a request, derive the client with a maxRetryCount.

    Declaration

    Swift

    static func retryWithBackoff(maxAttempts: Int? = 3,
                                 transientBaseDelay: TimeInterval = 0.1,
                                 throttlingBaseDelay: TimeInterval = 1,
                                 maxDelay: TimeInterval = 20,
                                 retryAfterAboveMaxDelay: RetryAfterAboveMaxDelay = .giveUp) -> RequestInterceptor

    Parameters

    maxAttempts

    the maximum number of consecutive attempts, including the initial one. nil means there is no cap.

    transientBaseDelay

    the base delay, in seconds, for retryable failures other than HTTP 429.

    throttlingBaseDelay

    the base delay, in seconds, for HTTP 429 responses.

    maxDelay

    the longest backoff delay, in seconds. A Retry-After up to this long is waited as a minimum; a longer one is handled per retryAfterAboveMaxDelay.

    retryAfterAboveMaxDelay

    what to do when a Retry-After header asks for longer than maxDelay: .giveUp stops proposing a retry, so another interceptor may still retry, and .wait waits for the full header, with no upper bound.

    Return Value

    a new RequestInterceptor; it keeps no state, so it can be shared between clients.