Skip to content

Class: CircuitBreaker

Package: @litert/concurrentImport path: @litert/concurrentSource: packages/partials/concurrent/src/Classes/CircuitBreaker.tsExtends: EventEmitter<ICircuitBreakerEvents>Implements: IBreaker

An automatic circuit breaker with three states:

  • Closed — all calls pass through; failures are counted.
  • Opened — all calls throw immediately; after cooldownTimeMs, transitions to Half-Open.
  • Half-Opened — one probe call passes through; if it succeeds (warmupThreshold consecutive successes), the breaker closes; if it fails, it re-opens.

Failure counting uses a sliding-window counter (default: 10-second window, 6 sub-windows). Inject a custom ICounter instance via the counter option to change the counting strategy.


Constructor

ts
new CircuitBreaker(opts?: ICircuitBreakerOptions)

See ICircuitBreakerOptions.


Methods

call(fn)

ts
call<TFn extends ISimpleFn>(fn: TFn): ReturnType<TFn>

Calls fn according to the current breaker state.

  • Closed: calls fn; counts the failure if it throws and isFailure returns true.
  • Opened: throws immediately without calling fn.
  • Half-Opened: lets the call through as a probe; updates state on result.

Throws: E_BREAKER_OPENED (or custom error) when open.


open(until?)

ts
open(until?: number): void

Manually opens the breaker.

ParameterTypeDescription
untilnumber?Unix timestamp (ms) when the cooldown ends; defaults to Date.now() + cooldownTimeMs

close()

ts
close(): void

Manually closes the breaker (resetting failure counter).


isOpened()

ts
isOpened(): boolean

Returns true if the breaker is currently in the open state.


isClosed()

ts
isClosed(): boolean

Returns true if the breaker is in the closed state.


isHalfOpened()

ts
isHalfOpened(): boolean

Returns true if the breaker is in the half-open state.


wrap(fn)

ts
wrap<T extends ISimpleFn>(fn: T): T

Returns a wrapper function that passes each call through the breaker.


Events

See ICircuitBreakerEvents.

EventDescription
'opened'Emitted when the breaker transitions to open state
'half_opened'Emitted when the breaker enters half-open state
'closed'Emitted when the breaker closes
'error'Emitted when the guarded function throws (does not prevent the error from propagating)

Example

ts
import { CircuitBreaker } from '@litert/concurrent';

const breaker = new CircuitBreaker({
    breakThreshold: 5,   // open after 5 failures within the window
    cooldownTimeMs: 30_000,
    warmupThreshold: 2,  // need 2 consecutive successes to close again
    isFailure: (err) => !(err instanceof NotFoundError), // don't count 404s
});

breaker.on('opened',      () => console.log('Circuit opened'));
breaker.on('half_opened', () => console.log('Circuit half-open (probing)'));
breaker.on('closed',      () => console.log('Circuit closed'));

function callDownstream() {
    try {
        return breaker.call(() => downstream.fetch());
    } catch (e) {
        if (e instanceof E_BREAKER_OPENED) {
            return cachedResponse();
        }
        throw e;
    }
}