Search documentation of macula

# macula_rpc_failover (macula v0.44.2)

View Source

RPC Failover Strategy Module

Encapsulates failover logic for RPC calls: - Determines if a call should be retried after failure - Manages provider exclusion list (failed providers) - Tracks attempt counts against max attempts - Provides retry decisions based on failure type

Extracted from macula_rpc_handler.erl (Dec 2025) to improve testability and separation of concerns.

# Summary

## Types

failover_context/0
failure_reason/0

## Functions

can_retry(Context)

Check if the call can be retried based on current context. Returns true if there are available providers and max attempts not exceeded.

get_attempt_count(_)

Get current attempt count.

get_available_providers(_)

Get list of providers that haven't been excluded. Filters out all previously failed providers.

increment_attempt(Context)

Increment the attempt counter. Call this before each retry attempt.

mark_provider_failed(NodeId, Context)

Mark a provider as failed and add to exclusion list. Returns updated context with provider added to excluded list.

new_context(Procedure, Args, Opts, Providers)

Create a new failover context for an RPC call. Used when initiating a call that might need failover. max_attempts is capped at provider count (can't try more providers than exist).

should_failover(_, Context)

Determine if failover should be attempted for a given failure reason. Some failures are not retryable (e.g., invalid procedure).

# Types

# failover_context/0

    -type failover_context() ::
              #{procedure := binary(),
                args := term(),
                opts := map(),
                providers := [map()],
                excluded := [binary()],
                attempt := pos_integer(),
                max_attempts := pos_integer(),
                tried_node_id => binary() | undefined}.

# failure_reason/0

    -type failure_reason() :: timeout | connection_error | provider_error | gateway_timeout.

# Functions

# can_retry(Context)

    -spec can_retry(failover_context()) -> boolean().

Check if the call can be retried based on current context. Returns true if there are available providers and max attempts not exceeded.

# get_attempt_count(_)

    -spec get_attempt_count(failover_context()) -> pos_integer().

Get current attempt count.

# get_available_providers(_)

    -spec get_available_providers(failover_context()) -> [map()].

Get list of providers that haven't been excluded. Filters out all previously failed providers.

# increment_attempt(Context)

    -spec increment_attempt(failover_context()) -> failover_context().

Increment the attempt counter. Call this before each retry attempt.

# mark_provider_failed(NodeId, Context)

    -spec mark_provider_failed(binary() | undefined, failover_context()) -> failover_context().

Mark a provider as failed and add to exclusion list. Returns updated context with provider added to excluded list.

# new_context(Procedure, Args, Opts, Providers)

    -spec new_context(binary(), term(), map(), [map()]) -> failover_context().

Create a new failover context for an RPC call. Used when initiating a call that might need failover. max_attempts is capped at provider count (can't try more providers than exist).

# should_failover(_, Context)

    -spec should_failover(failure_reason(), failover_context()) -> boolean().

Determine if failover should be attempted for a given failure reason. Some failures are not retryable (e.g., invalid procedure).