core.circuit_breaker module

Generic async circuit breaker.

CircuitBreaker trips to OPEN after failure_threshold consecutive failures, short-circuiting further calls with CircuitBreakerOpenException until reset_timeout elapses, then probes recovery via a HALF_OPEN trial call. Used to protect calls to fragile dependencies (e.g. Redis during ingress routing).

exception core.circuit_breaker.CircuitBreakerOpenException[source]

Bases: Exception

class core.circuit_breaker.CircuitBreaker(failure_threshold=3, reset_timeout=60.0)[source]

Bases: object

Parameters:
  • failure_threshold (int)

  • reset_timeout (float)

__init__(failure_threshold=3, reset_timeout=60.0)[source]

Initialize a closed circuit breaker with failure/reset tuning.

Sets up the in-memory state machine used to short-circuit calls to a fragile dependency. The breaker starts in the CLOSED state with a zeroed failure counter and no recorded last-failure time, so the first protected call always executes.

This is a pure in-memory initializer: it performs no I/O, touches no Redis/KG/LLM/HTTP collaborators, and only stores configuration and counters on self. State transitions happen later inside call(), _record_failure(), and _record_success(). It is constructed by core.strangler_router (and the top-level strangler_router shim) when wiring ingress routing, and directly in tests/core/migration/test_circuit_breaker.py.

Parameters:
  • failure_threshold (int) – Number of consecutive failures, while in the CLOSED state, that trips the breaker to OPEN. Defaults to 3.

  • reset_timeout (float) – Seconds the breaker stays OPEN before a subsequent call() is allowed through as a HALF_OPEN recovery probe. Defaults to 60.0.

async call(func, *args, **kwargs)[source]

Invoke an async callable through the breaker, enforcing the circuit state.

This is the single entry point that protects a fragile dependency. When the breaker is OPEN it checks whether reset_timeout has elapsed since the last failure: if so it transitions to HALF_OPEN (logging circuit_breaker_half_open) and lets one probe call through; otherwise it short-circuits immediately by raising CircuitBreakerOpenException without ever awaiting func.

When a call is allowed, it awaits func(*args, **kwargs). Any exception is routed through _record_failure() (which may trip or re-open the breaker) and then re-raised unchanged; a successful return is routed through _record_success() (which may close the breaker and clear the failure count) before the result is returned. The method reads the wall clock via time.time() and emits structured log lines on the stargazer.circuit_breaker logger; it performs no Redis, KG, LLM, or HTTP I/O of its own beyond whatever func does.

It is called by core.strangler_router / the top-level strangler_router shim to guard ingress route resolution, and by the circuit-breaker unit tests in tests/core/migration/test_circuit_breaker.py.

Parameters:
  • func (Callable[..., Any]) – The async callable to execute under breaker protection. Its __name__ is used only for log labels (falling back to "unknown_func").

  • *args – Positional arguments forwarded verbatim to func.

  • **kwargs – Keyword arguments forwarded verbatim to func.

Returns:

Whatever func returns when the call is permitted and succeeds.

Return type:

Any

Raises:
  • CircuitBreakerOpenException – If the breaker is OPEN and the reset timeout has not yet elapsed, so func is never invoked.

  • Exception – Re-raises, unchanged, any exception thrown by func after recording the failure.