Bloccs.Retry (bloccs v0.2.0)

Copy Markdown View Source

Runtime internals

Infrastructure called by compiler-generated pipelines — not part of the stable user API. You drive this through manifests, not by calling it directly; signatures may change between minor versions.

Retry policy evaluation for the runtime.

Pure decision functions over a node's [contract].retry declaration:

retry = { strategy = "exponential", max = 3, on = ["timeout"], base_ms = 100 }
  • strategy"constant" | "linear" | "exponential" (anything else → no backoff delay)

  • max — maximum number of retries (attempt 0 is the original delivery, so max = 3 means up to 4 total attempts)
  • on — list of failure-reason tags to retry; empty/absent means "retry any transient failure"
  • base_ms — backoff base in ms (default 100)

Some failures are permanent — retrying cannot help — and are never retried regardless of policy: inbound schema mismatches, unknown ports, non-map payloads, and effect capability denials.

Summary

Types

A parsed retry policy (or nil when none declared).

Functions

Milliseconds to wait before the retry that follows attempt (0-based).

Permanent failures: deterministic errors that retrying cannot fix. These are never retried even when a policy is declared.

The string tag used to match a failure reason against policy.on.

Should a message that failed with reason on its attempt-th try (0-based) be retried under policy?

Types

policy()

@type policy() :: %{
  :strategy => String.t(),
  :max => non_neg_integer(),
  :on => [String.t()],
  optional(:base_ms) => pos_integer() | nil
}

A parsed retry policy (or nil when none declared).

Functions

backoff_ms(policy, attempt)

@spec backoff_ms(policy(), non_neg_integer()) :: non_neg_integer()

Milliseconds to wait before the retry that follows attempt (0-based).

Backoff grows by strategy, seeded at base_ms, capped at 30000ms.

permanent?(arg1)

@spec permanent?(term()) :: boolean()

Permanent failures: deterministic errors that retrying cannot fix. These are never retried even when a policy is declared.

reason_tag(reason)

@spec reason_tag(term()) :: String.t()

The string tag used to match a failure reason against policy.on.

  • atom → its string form (:timeout"timeout")
  • tagged tuple → the tag ({:node_crash, _}"node_crash")
  • exception struct → "exception"
  • anything else → "error"

retriable?(reason, arg2, attempt)

@spec retriable?(term(), policy() | nil, non_neg_integer()) :: boolean()

Should a message that failed with reason on its attempt-th try (0-based) be retried under policy?

Returns false when no policy is declared, when reason is permanent, when attempt has already reached policy.max, or when policy.on is non-empty and doesn't list reason's tag.