Circuit Breaker
Top-level circuit-breaker primitive. Re-exports the CircuitBreaker class otherwise reachable as b.retry.CircuitBreaker, plus a create(opts) factory matching every other framework primitive's create() shape. The implementation lives in lib/retry.js so the retry classifier and the breaker share the isRetryable / observability emit conventions; this module is the operator-facing surface so callers don't have to know retry is the breaker's home.
State machine: closed (normal flow; failures count up to failureThreshold), open (every call fast-fails for cooldownMs), half (first probe closes the breaker on success or re-opens it on failure). Intended for per-target use — one instance per upstream service. Sharing a breaker across unrelated targets defeats the failure-threshold semantic.
b.circuitBreaker.create(opts) #
{
name: string, // identifier used in audit + state-change events
failureThreshold: number, // failures in the closed state before opening
cooldownMs: number, // milliseconds the breaker stays open before probing
successThreshold: number, // probe successes required to close from half-open
onStateChange: Function, // ({ name, from, to, at }) → void; also emits the
// `breaker.state.change` observability event
}
Build a circuit-breaker. Returns a CircuitBreaker instance with wrap(fn) (executes fn if the breaker is closed; throws an Error with code: "CIRCUIT_OPEN" + isObjectStoreError: true + permanent: false when open), getState(), reset(), and onStateChange(handler) listener registration (the handler, and the onStateChange opt, receive { name, from, to, at } on every transition). Pass-through factory: identical instance shape to b.retry.CircuitBreaker, with the framework's create(opts) vocabulary.
The CIRCUIT_OPEN error code is a pre-v1 artifact — every other framework error class uses namespaced codes (retry/...). It is kept through the pre-1.0 line so existing operators who match err.code === "CIRCUIT_OPEN" aren't broken in a patch; the rename to a namespaced code lands at v1.0 alongside the namespaced-error sweep, with a deprecation warning shipping a minor ahead.
var cb = b.circuitBreaker.create({
name: "upstream-billing",
failureThreshold: 5,
cooldownMs: 30000,
successThreshold: 2,
onStateChange: function (e) {
// e = { name, from: "closed", to: "open", at: }
},
});
var result = await cb.wrap(async function () {
return { ok: true, value: 42 };
});
result.value; // → 42
Last updated 2026-08-08T16:39:49.652Z by seeder.