ClearBank.HTTP.Retry (ClearBank v1.0.0)

Copy Markdown View Source

Exponential backoff retry logic for ClearBank API calls.

ClearBank's documentation states:

  • 5XX errors are safe to retry using the exact same X-Request-Id and payload.
  • 429 (rate limited): back off and retry.
  • 409 (duplicate X-Request-Id): do NOT retry.

Usage

import ClearBank.HTTP.Retry

{:ok, result} = with_retry(fn ->
  ClearBank.Payments.FasterPayments.send(client, payment)
end)

{:ok, result} = with_retry(
  fn -> ClearBank.Accounts.list(client) end,
  max_attempts: 5,
  base_delay_ms: 500,
  max_delay_ms: 30_000
)

Important: idempotency

When retrying mutating requests (POST/PUT/PATCH), pass a stable :request_id so ClearBank's idempotency guarantee is preserved across retries:

stable_id = ClearBank.HTTP.generate_request_id()

with_retry(fn ->
  ClearBank.HTTP.post(client, "/v3/Payments/FPS", body, request_id: stable_id)
end)

Summary

Functions

Executes fun with automatic exponential-backoff retries on retryable errors.

Types

retry_opts()

@type retry_opts() :: [
  max_attempts: pos_integer(),
  base_delay_ms: non_neg_integer(),
  max_delay_ms: non_neg_integer(),
  jitter: boolean()
]

Functions

with_retry(fun, opts \\ [])

@spec with_retry(fun(), retry_opts()) :: {:ok, term()} | {:error, ClearBank.Error.t()}

Executes fun with automatic exponential-backoff retries on retryable errors.

Returns {:ok, result} on success, or {:error, %ClearBank.Error{}} after all attempts are exhausted.

Options

  • :max_attempts - total attempts including the first (default: 3)
  • :base_delay_ms - initial backoff delay in ms (default: 1_000)
  • :max_delay_ms - maximum delay cap in ms (default: 30_000)
  • :jitter - add random jitter to delays to avoid thundering herd (default: true)

Examples

{:ok, accounts} = ClearBank.HTTP.Retry.with_retry(fn ->
  ClearBank.Accounts.list(client)
end)

{:ok, _} = ClearBank.HTTP.Retry.with_retry(
  fn -> ClearBank.Accounts.list(client) end,
  max_attempts: 5,
  base_delay_ms: 200
)