ExMCP.Reliability.CircuitBreaker.Core (ex_mcp v1.3.0)

Copy Markdown View Source

Pure circuit-breaker state machine used by ExMCP.Reliability.CircuitBreaker.

All elapsed-duration decisions use an injected now_ms value. The process shell passes System.monotonic_time(:millisecond) so open and half-open timeouts cannot go backwards when the wall clock is adjusted. Stored timestamps (opened_at, last_failure_time, last_success_time, and stats.created_at) are on that same monotonic millisecond scale.

This module does not call System or Process. Callers must supply now_ms; there is no default clock here.

Summary

Functions

Checks if a request should be allowed based on the current circuit state.

Checks if a request should be allowed and returns both the result and updated state.

Forces the circuit breaker to a specific state.

Gets the current state of the circuit breaker.

Gets circuit breaker statistics.

Creates a new circuit breaker with the given configuration.

Records a failed operation and updates the circuit breaker state.

Records a successful operation and updates the circuit breaker state.

Resets the circuit breaker to its initial state.

Types

config()

@type config() :: %{
  failure_threshold: non_neg_integer(),
  success_threshold: non_neg_integer(),
  timeout: non_neg_integer(),
  failure_rate_threshold: float(),
  minimum_throughput: non_neg_integer(),
  reset_timeout: non_neg_integer()
}

now_ms()

@type now_ms() :: integer()

state()

@type state() :: :closed | :open | :half_open

t()

@type t() :: %ExMCP.Reliability.CircuitBreaker.Core{
  config: map(),
  failure_count: non_neg_integer(),
  last_failure_time: now_ms() | nil,
  last_success_time: now_ms() | nil,
  opened_at: now_ms() | nil,
  state: state(),
  stats: map(),
  success_count: non_neg_integer()
}

Functions

allow_request?(circuit_breaker, now_ms)

@spec allow_request?(t(), now_ms()) :: boolean()

Checks if a request should be allowed based on the current circuit state.

allow_request_with_state?(circuit_breaker, now_ms)

@spec allow_request_with_state?(t(), now_ms()) :: {boolean(), t()}

Checks if a request should be allowed and returns both the result and updated state.

force_state(circuit_breaker, new_state, now_ms)

@spec force_state(t(), state(), now_ms()) :: t()

Forces the circuit breaker to a specific state.

get_state(circuit_breaker, now_ms)

@spec get_state(t(), now_ms()) :: state()

Gets the current state of the circuit breaker.

get_stats(circuit_breaker)

@spec get_stats(t()) :: map()

Gets circuit breaker statistics.

new(config \\ %{}, now_ms)

@spec new(config() | map(), now_ms()) :: t()

Creates a new circuit breaker with the given configuration.

now_ms is recorded as stats.created_at. Pass a monotonic millisecond value from the process shell.

record_failure(circuit_breaker, now_ms)

@spec record_failure(t(), now_ms()) :: t()

Records a failed operation and updates the circuit breaker state.

record_success(circuit_breaker, now_ms)

@spec record_success(t(), now_ms()) :: t()

Records a successful operation and updates the circuit breaker state.

reset(circuit_breaker)

@spec reset(t()) :: t()

Resets the circuit breaker to its initial state.