Liking cljdoc? Tell your friends :D

supabase.core.retry

Pure retry policy for transient HTTP failures in the Supabase Clojure SDK.

This namespace decides whether and how long to wait before retrying a failed request. It performs no sleeping and no I/O: supabase.core.http calls these functions from its retry loop and owns the actual waiting.

Transient failures

A failure is worth retrying when it is likely to resolve on its own:

  • HTTP statuses 429, 502, 503, 504 (transient-status?)
  • Transport exceptions: connection refused, connect/read timeouts, no route to host, reset or broken-pipe sockets, and unexpected EOF (transient-exception?, which also walks the cause chain)

Delay computation

Delays combine two sources, with the server always winning:

  1. A Retry-After response header, when present and parseable (retry-after-ms), either as delay-seconds or an RFC 1123 HTTP-date.
  2. Exponential backoff with full jitter (backoff-ms), capped at :max-delay-ms.

next-delay-ms applies that precedence. merge-opts resolves client-level and request-level retry options against default-opts.

Usage

(require '[supabase.core.retry :as retry])

(retry/transient-status? 503)              ;; => true
(retry/retry-after-ms {"retry-after" "3"}) ;; => 3000
(retry/backoff-ms 2)                       ;; => long in [0, 400]
(retry/next-delay-ms 2 {"retry-after" "3"}) ;; => 3000
(retry/merge-opts {:max-attempts 5} true)  ;; => {:max-attempts 5, ...}
Pure retry policy for transient HTTP failures in the Supabase Clojure SDK.

This namespace decides *whether* and *how long* to wait before retrying a
failed request. It performs no sleeping and no I/O: `supabase.core.http`
calls these functions from its retry loop and owns the actual waiting.

## Transient failures

A failure is worth retrying when it is likely to resolve on its own:

  - HTTP statuses 429, 502, 503, 504 (`transient-status?`)
  - Transport exceptions: connection refused, connect/read timeouts, no
    route to host, reset or broken-pipe sockets, and unexpected EOF
    (`transient-exception?`, which also walks the cause chain)

## Delay computation

Delays combine two sources, with the server always winning:

  1. A `Retry-After` response header, when present and parseable
     (`retry-after-ms`), either as delay-seconds or an RFC 1123 HTTP-date.
  2. Exponential backoff with full jitter (`backoff-ms`), capped at
     `:max-delay-ms`.

`next-delay-ms` applies that precedence. `merge-opts` resolves client-level
and request-level retry options against `default-opts`.

## Usage

    (require '[supabase.core.retry :as retry])

    (retry/transient-status? 503)              ;; => true
    (retry/retry-after-ms {"retry-after" "3"}) ;; => 3000
    (retry/backoff-ms 2)                       ;; => long in [0, 400]
    (retry/next-delay-ms 2 {"retry-after" "3"}) ;; => 3000
    (retry/merge-opts {:max-attempts 5} true)  ;; => {:max-attempts 5, ...}
raw docstring

backoff-msclj

(backoff-ms attempt)
(backoff-ms attempt opts)

Exponential backoff with full jitter for the given 1-based attempt.

The delay cap is min(max-delay-ms, initial-delay-ms * multiplier^(attempt-1)); the result is a uniformly random long in [0, cap]. Missing option keys fall back to default-opts.

(backoff-ms 1) ;; => long in [0, 200] with default opts
Exponential backoff with full jitter for the given 1-based `attempt`.

The delay cap is `min(max-delay-ms, initial-delay-ms * multiplier^(attempt-1))`;
the result is a uniformly random long in [0, cap]. Missing option keys fall
back to `default-opts`.

    (backoff-ms 1) ;; => long in [0, 200] with default opts
sourceraw docstring

default-optsclj

Default retry options.

Default retry options.
sourceraw docstring

merge-optsclj

(merge-opts client-opts request-opts)

Resolves retry options from defaults, client-level opts, and a request-level override.

The request override may be:

  • nil/absent: client opts win
  • false: retry disabled (returns nil)
  • true: client opts (or defaults) as-is
  • integer N: client opts with :max-attempts N
  • map: merged over client opts

Client opts may likewise be true (use defaults), an integer (:max-attempts), or a map. Returns a resolved opts map containing every key of default-opts, or nil when retries are disabled.

(merge-opts {:max-attempts 5} false) ;; => nil
(merge-opts true 5)                  ;; => (assoc default-opts :max-attempts 5)
Resolves retry options from defaults, client-level opts, and a
request-level override.

The request override may be:

  - nil/absent: client opts win
  - false:      retry disabled (returns nil)
  - true:       client opts (or defaults) as-is
  - integer N:  client opts with `:max-attempts` N
  - map:        merged over client opts

Client opts may likewise be true (use defaults), an integer
(`:max-attempts`), or a map. Returns a resolved opts map containing every
key of `default-opts`, or nil when retries are disabled.

    (merge-opts {:max-attempts 5} false) ;; => nil
    (merge-opts true 5)                  ;; => (assoc default-opts :max-attempts 5)
sourceraw docstring

next-delay-msclj

(next-delay-ms attempt headers)
(next-delay-ms attempt headers opts)

Delay in milliseconds before the next attempt.

An honored Retry-After header in headers wins over computed backoff; otherwise returns backoff-ms for attempt. Returns a long.

(next-delay-ms 1 {"retry-after" "3"}) ;; => 3000
(next-delay-ms 1 {})                    ;; => long in [0, 200]
Delay in milliseconds before the next attempt.

An honored Retry-After header in `headers` wins over computed backoff;
otherwise returns `backoff-ms` for `attempt`. Returns a long.

    (next-delay-ms 1 {"retry-after" "3"}) ;; => 3000
    (next-delay-ms 1 {})                    ;; => long in [0, 200]
sourceraw docstring

retry-after-msclj

(retry-after-ms headers)

Parses a Retry-After header value from a response headers map.

Headers arrive with lower-case string keys, so the lookup key is "retry-after". The value may be a non-negative integer (delay-seconds) or an HTTP-date (RFC 1123, e.g. "Tue, 18 Aug 2026 12:00:00 GMT"). Negative integer values are clamped to 0. Returns the delay in milliseconds as a long, or nil when the header is absent or unparseable. Never throws.

(retry-after-ms {"retry-after" "3"})  ;; => 3000
(retry-after-ms {})                     ;; => nil
Parses a Retry-After header value from a response headers map.

Headers arrive with lower-case string keys, so the lookup key is
"retry-after". The value may be a non-negative integer (delay-seconds)
or an HTTP-date (RFC 1123, e.g. "Tue, 18 Aug 2026 12:00:00 GMT").
Negative integer values are clamped to 0. Returns the delay in
milliseconds as a long, or nil when the header is absent or unparseable.
Never throws.

    (retry-after-ms {"retry-after" "3"})  ;; => 3000
    (retry-after-ms {})                     ;; => nil
sourceraw docstring

transient-exception?clj

(transient-exception? ex)

True for exceptions that indicate a transient transport failure: java.net.ConnectException, java.net.http.HttpConnectTimeoutException, java.net.http.HttpTimeoutException, java.net.NoRouteToHostException, java.net.SocketException whose message contains "Connection reset" or "Broken pipe" (case-insensitive), and java.io.EOFException.

Walks the cause chain, so a transient failure wrapped in another exception (for example via ex-info) is still detected.

True for exceptions that indicate a transient transport failure:
`java.net.ConnectException`, `java.net.http.HttpConnectTimeoutException`,
`java.net.http.HttpTimeoutException`, `java.net.NoRouteToHostException`,
`java.net.SocketException` whose message contains "Connection reset" or
"Broken pipe" (case-insensitive), and `java.io.EOFException`.

Walks the cause chain, so a transient failure wrapped in another exception
(for example via `ex-info`) is still detected.
sourceraw docstring

transient-status?clj

(transient-status? status)

True for HTTP statuses worth retrying: 429, 502, 503, 504.

True for HTTP statuses worth retrying: 429, 502, 503, 504.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close