macula_rpc_failover (macula v0.20.5)
View SourceRPC 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
Functions
Check if the call can be retried based on current context. Returns true if there are available providers and max attempts not exceeded.
Get current attempt count.
Get list of providers that haven't been excluded. Filters out all previously failed providers.
Increment the attempt counter. Call this before each retry attempt.
Mark a provider as failed and add to exclusion list. Returns updated context with provider added to excluded list.
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).
Determine if failover should be attempted for a given failure reason. Some failures are not retryable (e.g., invalid procedure).
Types
-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}.
-type failure_reason() :: timeout | connection_error | provider_error | gateway_timeout.
Functions
-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.
-spec get_attempt_count(failover_context()) -> pos_integer().
Get current attempt count.
-spec get_available_providers(failover_context()) -> [map()].
Get list of providers that haven't been excluded. Filters out all previously failed providers.
-spec increment_attempt(failover_context()) -> failover_context().
Increment the attempt counter. Call this before each retry attempt.
-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.
-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).
-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).