Exponential backoff retry logic for ClearBank API calls.
ClearBank's documentation states:
- 5XX errors are safe to retry using the exact same
X-Request-Idand 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
@type retry_opts() :: [ max_attempts: pos_integer(), base_delay_ms: non_neg_integer(), max_delay_ms: non_neg_integer(), jitter: boolean() ]
Functions
@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
)