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 (
warmupThresholdconsecutive 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
new CircuitBreaker(opts?: ICircuitBreakerOptions)Methods
call(fn)
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 andisFailurereturnstrue. - 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?)
open(until?: number): voidManually opens the breaker.
| Parameter | Type | Description |
|---|---|---|
until | number? | Unix timestamp (ms) when the cooldown ends; defaults to Date.now() + cooldownTimeMs |
close()
close(): voidManually closes the breaker (resetting failure counter).
isOpened()
isOpened(): booleanReturns true if the breaker is currently in the open state.
isClosed()
isClosed(): booleanReturns true if the breaker is in the closed state.
isHalfOpened()
isHalfOpened(): booleanReturns true if the breaker is in the half-open state.
wrap(fn)
wrap<T extends ISimpleFn>(fn: T): TReturns a wrapper function that passes each call through the breaker.
Events
| Event | Description |
|---|---|
'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
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;
}
}