CircuitBreakerExecutor
CircuitBreakerExecutor wraps task execution with a circuit breaker that tracks failures and prevents calls to a failing service. It cycles through CLOSED, OPEN, and HALF_OPEN states.
Best for resilient service calls Use
CircuitBreakerExecutorwhen calling external services that may fail, to avoid cascading failures and allow recovery time.
Import
Section titled “Import”Root package:
import { CircuitBreakerExecutor } from "@vgerbot/async";Module subpath:
import { CircuitBreakerExecutor } from "@vgerbot/async/executors";Leaf subpath:
import { CircuitBreakerExecutor } from "@vgerbot/async/executors/CircuitBreakerExecutor";Quick example
Section titled “Quick example”import { CircuitBreakerExecutor } from "@vgerbot/async";
const breaker = new CircuitBreakerExecutor({ failureThreshold: 5, // Open after 5 consecutive failures successThreshold: 3, // Close after 3 consecutive successes in half-open resetTimeout: 10_000, // Wait 10s before transitioning to half-open});
for (let i = 0; i < 10; i++) { try { const result = await breaker.exec(async (token) => { return fetch("/api/unstable-service"); }); } catch (error) { console.log(`Request ${i} failed:`, error.message); }}
console.log("Circuit state:", breaker.getState()); // "closed" | "open" | "half_open"When to use CircuitBreakerExecutor
Section titled “When to use CircuitBreakerExecutor”- External service calls: Protect against cascading failures when a dependency is down.
- Database connections: Avoid hammering a database that is temporarily unavailable.
- API gateways: Prevent requests to a failing downstream service.
- Microservice resilience: Isolate failures in a microservice architecture.
type CircuitState = "closed" | "open" | "half_open";
class CircuitBreakerExecutor extends BaseTaskExecutor { constructor(options: CircuitBreakerOptions);
exec<T>(task: AsyncTask<T>, options?: TaskOptions): TaskHandle<T>; cancel(reason?: unknown): void; shutdown(reason?: unknown): void; isCancelled(): boolean;
getState(): CircuitState; reset(): void;}Constructor
Section titled “Constructor”new CircuitBreakerExecutor(options: CircuitBreakerOptions)CircuitBreakerOptions
Section titled “CircuitBreakerOptions”| Option | Type | Default | Description |
|---|---|---|---|
failureThreshold |
number |
5 |
Number of consecutive failures before opening the circuit. |
successThreshold |
number |
3 |
Number of consecutive successes in half-open state before closing. |
resetTimeout |
number |
10_000 |
Milliseconds to wait in open state before transitioning to half-open. |
Methods
Section titled “Methods”exec(task, options?)
Section titled “exec(task, options?)”Submits a task. If the circuit is open, the task is rejected immediately with a CircuitBreakerOpenError. If the circuit is closed or half-open, the task is executed and its success/failure updates the breaker state.
getState()
Section titled “getState()”Returns the current circuit state: "closed", "open", or "half_open".
reset()
Section titled “reset()”Manually resets the circuit breaker to the closed state, clearing all failure and success counters.
Execution model
Section titled “Execution model”States
Section titled “States”- CLOSED: Tasks are executed normally. Failures increment the failure counter. When failures reach
failureThreshold, the circuit opens. - OPEN: Tasks are rejected immediately without execution. After
resetTimeoutmilliseconds, the circuit transitions to half-open. - HALF_OPEN: A limited number of tasks are allowed through. Successes increment the success counter; failures re-open the circuit. When successes reach
successThreshold, the circuit closes.
CLOSED --(failures >= threshold)--> OPENOPEN --(resetTimeout elapsed)--> HALF_OPENHALF_OPEN --(successes >= threshold)--> CLOSEDHALF_OPEN --(any failure)--> OPENError handling
Section titled “Error handling”Task failures
Section titled “Task failures”When a task fails in the closed state, the failure is counted. If the failure threshold is reached, the circuit opens.
Circuit open
Section titled “Circuit open”When the circuit is open, exec rejects immediately with a CircuitBreakerOpenError:
try { await breaker.exec(async () => { return fetch("/api/service"); });} catch (error) { if (error instanceof CircuitBreakerOpenError) { console.log("Circuit is open — service likely down"); } else { console.log("Task failed:", error); }}Manual reset
Section titled “Manual reset”// Force reset after fixing the downstream servicebreaker.reset();console.log(breaker.getState()); // "closed"Cancellation
Section titled “Cancellation”Calling cancel() cancels current/pending tasks. To permanently disable the executor, call shutdown().
TypeScript tips
Section titled “TypeScript tips”exec is generic over T.
const result = await breaker.exec(async (token) => { const res = await token.wrap(fetch("/api/data")); return res.json() as Promise<{ status: string }>;});Related APIs
Section titled “Related APIs”PoolTaskExecutor— concurrency-limited pool.RateLimitExecutor— rate-limited executor.retry— retry individual tasks on failure.timeout— wrap tasks with a deadline.ITaskExecutor— common executor interface.