@juspay/neurolink
Version:
The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002
150 lines (149 loc) • 5.03 kB
TypeScript
/**
* MCP Circuit Breaker
* Implements circuit breaker pattern for external MCP operations
* Provides fault tolerance and prevents cascading failures
*/
import { EventEmitter } from "events";
import type { CircuitBreakerConfig, CircuitBreakerStats } from "../types/index.js";
export { CircuitBreakerOpenError } from "../types/index.js";
/**
* MCPCircuitBreaker
* Implements circuit breaker pattern for fault tolerance
*/
export declare class MCPCircuitBreaker extends EventEmitter {
private name;
private state;
private config;
private callHistory;
private lastFailureTime;
private halfOpenCalls;
private lastStateChange;
private cleanupTimer?;
constructor(name: string, config?: Partial<CircuitBreakerConfig>);
/**
* Execute an operation with circuit breaker protection.
*
* `operation` is handed a `recordResolvedFailure` callback so it can flag a
* *resolved* result as a logical failure without throwing. This matters for
* MCP tool calls: the client does not throw on a protocol error, it
* resolves with `{ isError: true, ... }`. Before this callback existed,
* such a call always fell through to the success path below — the breaker
* could never open for a tool that only ever "fails" by resolving an error
* result, and callers still need that resolved value returned as-is (not
* replaced by a thrown transport error). Call `recordResolvedFailure()`
* from inside `operation` when that resolved value represents a failure;
* the call is still counted as a normal, non-throwing success from the
* `Promise.race` below, so this callback is what tells `execute()`
* otherwise. Callers that never call it see no behavior change.
*/
execute<T>(operation: (recordResolvedFailure: (reason?: string) => void) => Promise<T>): Promise<T>;
/**
* Shared bookkeeping for a failed outcome — a thrown error, or a resolved
* result the caller flagged via `recordResolvedFailure`. Records the call
* as a failure, emits `callFailure`, and runs the state transitions that
* used to live inline in the `catch` block: half-open failure immediately
* re-opens the circuit; closed checks the failure threshold.
*/
private recordFailureOutcome;
/**
* Record a call in the history
*/
private recordCall;
/**
* Check if failure threshold is exceeded
*/
private checkFailureThreshold;
/**
* Change circuit breaker state
*/
private changeState;
/**
* Race an operation against a timeout, clearing the timer on either
* outcome. A bare `Promise.race([operation, timeoutPromise])` leaves the
* timeout's `setTimeout` handle ref'd and pending until it fires even
* after `operation` already won the race — on the (common) success path
* that stray timer holds the event loop open for the full timeout
* duration for no reason.
*/
private raceWithTimeout;
/**
* Clean up old call records
*/
private cleanupCallHistory;
/**
* Get current statistics
*/
getStats(): CircuitBreakerStats;
/**
* Manually reset the circuit breaker
*/
reset(): void;
/**
* Force open the circuit breaker
*/
forceOpen(reason?: string): void;
/**
* Get circuit breaker name
*/
getName(): string;
/**
* Check if circuit is open
*/
isOpen(): boolean;
/**
* Check if circuit is closed
*/
isClosed(): boolean;
/**
* Check if circuit is half-open
*/
isHalfOpen(): boolean;
/**
* Destroy the circuit breaker and clean up resources
* This method should be called when the circuit breaker is no longer needed
* to prevent memory leaks from the cleanup timer
*/
destroy(): void;
}
/**
* Circuit breaker manager for multiple circuit breakers
*/
export declare class CircuitBreakerManager {
private breakers;
/**
* Get or create a circuit breaker
*/
getBreaker(name: string, config?: Partial<CircuitBreakerConfig>): MCPCircuitBreaker;
/**
* Remove a circuit breaker and clean up its resources
*/
removeBreaker(name: string): boolean;
/**
* Get all circuit breaker names
*/
getBreakerNames(): string[];
/**
* Get statistics for all circuit breakers
*/
getAllStats(): Record<string, CircuitBreakerStats>;
/**
* Reset all circuit breakers
*/
resetAll(): void;
/**
* Get health summary
*/
getHealthSummary(): {
totalBreakers: number;
closedBreakers: number;
openBreakers: number;
halfOpenBreakers: number;
unhealthyBreakers: string[];
};
/**
* Destroy all circuit breakers and clean up their resources
* This should be called during application shutdown to prevent memory leaks
*/
destroyAll(): void;
}
export declare const globalCircuitBreakerManager: CircuitBreakerManager;