@types/opossum
Version:
TypeScript definitions for opossum
444 lines (384 loc) • 15.6 kB
TypeScript
/// <reference types="node"/>
import { EventEmitter } from "events";
declare class CircuitBreaker<TI extends unknown[] = unknown[], TR = unknown> extends EventEmitter {
static isOurError(error: Error): boolean;
static newStatus(options: CircuitBreaker.StatusOptions): CircuitBreaker.Status;
constructor(action: (...args: TI) => Promise<TR>, options?: CircuitBreaker.Options<TI>);
/**
* Gets the name of this circuit
*/
readonly name: string;
/**
* Gets the name of this circuit group
*/
readonly group: string;
/**
* Gets whether the circuit is enabled or not
*/
readonly enabled: boolean;
/**
* Gets whether this circuit is in the pendingClosed state
*/
readonly pendingClose: boolean;
/**
* True if the circuit is currently closed. False otherwise.
*/
readonly closed: boolean;
/**
* True if the circuit is currently opened. False otherwise.
*/
readonly opened: boolean;
/**
* True if the circuit is currently half opened. False otherwise.
*/
readonly halfOpen: boolean;
/**
* Determines if the circuit has been shutdown.
*/
readonly isShutdown: boolean;
/**
* The current {@link CircuitBreaker.Status} of this {@link CircuitBreaker}
*/
readonly status: CircuitBreaker.Status;
/**
* Get the current stats for the circuit.
*/
readonly stats: CircuitBreaker.Stats;
/**
* Gets whether the circuit is currently in warm up phase
*/
readonly warmUp: boolean;
/**
* Gets the volume threshold for this circuit
*/
readonly volumeThreshold: number;
/**
* Execute the action for this circuit using context as this.
* If the action fails or times out, the returned promise will be rejected.
* If the action succeeds, the promise will resolve with the resolved value from action.
* If a fallback function was provided, it will be invoked in the event of any failure or timeout.
* Any parameters in addition to `context` will be passed to the circuit function.
*/
call(context: any, ...args: TI): Promise<TR>;
/**
* Returns the current state of the circuit
*/
toJSON(): { state: CircuitBreaker.State; status: CircuitBreaker.Stats };
/**
* Clears the cache of this {@link CircuitBreaker}
*/
clearCache(): void;
/**
* Closes the breaker, allowing the action to execute again
*/
close(): void;
/**
* Opens the breaker.
* Each time the breaker is fired while the circuit is opened, a failed Promise is
* returned, or if any fallback function has been provided, it is invoked.
*/
open(): void;
/**
* Shuts down this circuit breaker.
* All subsequent calls to the circuit will fail, returning a rejected promise.
*/
shutdown(): void;
/**
* Disables this circuit, causing all calls to the circuit's function to be
* executed without circuit or fallback protection.
*/
disable(): void;
/**
* Enables this circuit. If the circuit is the disabled state, it will be re-enabled.
* If not, this is essentially a noop.
*/
enable(): void;
/**
* Provide a fallback function for this {@link CircuitBreaker}.
* This function will be executed when the circuit is fired and fails.
* It will always be preceded by a `failure` event, and `breaker.fire` returns a rejected Promise.
*/
fallback(func: ((...args: any[]) => any) | CircuitBreaker): this;
/**
* Execute the action for this circuit.
* If the action fails or times out, the returned promise will be rejected.
* If the action succeeds, the promise will resolve with the resolved value from action.
* If a fallback function was provided, it will be invoked in the event of any failure or timeout.
* Any parameters passed to this function will be proxied to the circuit function.
*/
fire(...args: TI): Promise<TR>;
/**
* Provide a health check function to be called periodically.
* The function should return a Promise. If the promise is rejected the circuit will open.
* This is in addition to the existing circuit behavior as defined by the
* `errorThresholdPercentage` option passed to the constructor.
* For example, if the health check function provided here always returns a resolved promise,
* the circuit can still trip and open if there are failures exceeding the configured threshold.
* The health check function is executed within the circuit breaker's execution context,
* so this within the function is the circuit breaker itself.
*
* The interval is the amount of time between calls to the health check function.
* Default: 5000 (5 seconds)
*/
healthCheck(func: () => Promise<void>, interval?: number): void;
/**
* Emitted after `options.resetTimeout` has elapsed, allowing for a single attempt to call the service again.
* If that attempt is successful, the circuit will be closed. Otherwise it remains open.
*/
on(event: "halfOpen", listener: (resetTimeout: number) => void): this;
/**
* Emitted when the breaker is reset allowing the action to execute again.
*/
on(event: "close", listener: () => void): this;
/**
* Emitted when the breaker opens because the action has failure percentage greater than `options.errorThresholdPercentage`.
*/
on(event: "open", listener: () => void): this;
/**
* Emitted when the circuit breaker has been shut down.
*/
on(event: "shutdown", listener: () => void): this;
/**
* Emitted when the circuit breaker action is executed.
*/
on(event: "fire", listener: (args: TI) => void): this;
/**
* Emitted when the circuit breaker is using the cache and finds a value.
*/
on(event: "cacheHit", listener: () => void): this;
/**
* Emitted when the circuit breaker does not find a value in the cache, but the cache option is enabled.
*/
on(event: "cacheMiss", listener: () => void): this;
/**
* Emitted when the circuit breaker is open and failing fast.
*/
on(event: "reject", listener: (err: Error) => void): this;
/**
* Emitted when the circuit breaker action takes longer than `options.timeout`.
*/
on(event: "timeout", listener: (err: Error) => void): this;
/**
* Emitted when the circuit breaker action succeeds.
*/
on(event: "success", listener: (result: TR, latencyMs: number) => void): this;
/**
* Emitted when the rate limit has been reached and there are no more locks to be obtained.
*/
on(event: "semaphoreLocked", listener: (err: Error) => void): this;
/**
* Emitted with the user-supplied health check function returns a rejected promise.
*/
on(event: "healthCheckFailed", listener: (err: Error) => void): this;
/**
* Emitted when the circuit breaker executes a fallback function.
*/
on(event: "fallback", listener: (result: unknown, err: Error) => void): this;
/**
* Emitted when the circuit breaker action fails.
*/
on(event: "failure", listener: (err: Error, latencyMs: number, args: TI) => void): this;
}
declare namespace CircuitBreaker {
interface Options<TI extends unknown[] = unknown[]> {
/**
* A {@link Status} object that might have pre-prime stats
*/
status?: Status | undefined;
/**
* The time in milliseconds that action should be allowed to execute before timing out.
* Timeout can be disabled by setting this to `false`.
* @default 10000 (10 seconds)
*/
timeout?: number | false | undefined;
/**
* The number of times the circuit can fail before opening.
* @default 10
* @deprecated
* @see {@link Options.errorThresholdPercentage}
*/
maxFailures?: number | undefined;
/**
* The time in milliseconds to wait before setting the breaker to `halfOpen` state, and trying the action again.
* @default 30000 (30 seconds)
*/
resetTimeout?: number | undefined;
/**
* Sets the duration of the statistical rolling window, in milliseconds.
* This is how long Opossum keeps metrics for the circuit breaker to use and for publishing.
* @default 10000
*/
rollingCountTimeout?: number | undefined;
/**
* Sets the number of buckets the rolling statistical window is divided into.
* So, if `options.rollingCountTimeout` is 10,000, and `options.rollingCountBuckets` is 10, then the
* statistical window will be 1,000 per 1 second snapshots in the statistical window.
* @default 10
*/
rollingCountBuckets?: number | undefined;
/**
* The circuit name to use when reporting stats.
* Defaults to the name of the function this circuit controls then falls back to a UUID
*/
name?: string | undefined;
/**
* (Undocumented)
* A grouping key for reporting.
* Defaults to the computed value of `name`
*/
group?: string | undefined;
/**
* This property indicates whether execution latencies should be tracked and calculated as percentiles.
* If they are disabled, all summary statistics (mean, percentiles) are returned as -1.
* @default false
*/
rollingPercentilesEnabled?: boolean | undefined;
/**
* The number of concurrent requests allowed.
* If the number currently executing function calls is equal to `options.capacity`, further calls
* to `fire()` are rejected until at least one of the current requests completes.
* @default Number.MAX_SAFE_INTEGER
*/
capacity?: number | undefined;
/**
* The error percentage at which to open the circuit and start short-circuiting requests to fallback.
* @default 50
*/
errorThresholdPercentage?: number | undefined;
/**
* Whether this circuit is enabled upon construction.
* @default true
*/
enabled?: boolean | undefined;
/**
* Determines whether to allow failures without opening the circuit during a brief warmup period (`rollingCountTimeout`)
* This can help in situations where no matter what your `errorThresholdPercentage` is, if the
* first execution times out or fails, the circuit immediately opens.
* @default false
*/
allowWarmUp?: boolean | undefined;
/**
* The minimum number of requests within the rolling statistical window that must exist before
* the circuit breaker can open. This is similar to `allowWarmUp` in that no matter how many
* failures there are, if the number of requests within the statistical window does not exceed
* this threshold, the circuit will remain closed.
* @default 0
*/
volumeThreshold?: number | undefined;
/**
* An optional function that will be called when the circuit's function fails (returns a rejected Promise).
* If this function returns truthy, the circuit's `failPure` statistics will not be incremented.
* This is useful, for example, when you don't want HTTP 404 to trip the circuit, but still want to handle it as a failure case.
*/
errorFilter?: ((err: any) => boolean) | undefined;
/**
* Whether the return value of the first successful execution of the circuit's function will be cached.
* Once a value has been cached that value will be returned for every subsequent execution: the cache can be cleared using `clearCache`.
* (The metrics cacheHit and cacheMiss reflect cache activity.)
* @default false
*/
cache?: boolean | undefined;
/**
* The cache time to live (TTL) in milliseconds.
* The default value is 0, which means the cache will never be cleared.
* @default 0 (no TTL)
*/
cacheTTL?: number;
/**
* An optional function that will be called to generate a cache key for the circuit's function.
* The function is passed the original `fire` arguments. If no `cacheKey` function is supplied, a `JSON.stringify` of the arguments will be used as the key.
* @default (...args) => JSON.stringify(args)
*/
cacheGetKey?: ((...args: TI) => string) | undefined;
/**
* Transport for cache storage. By default, the cache is stored in memory.
* If a cacheTransport is provided, the cache will be stored there instead.
*/
cacheTransport?: CacheTransport | undefined;
/**
* If present, Opossum can signal upon timeout and properly abort your on going requests instead of leaving it in the background.
*/
abortController?: AbortController | undefined;
/**
* Whether to enable the periodic snapshots that are emitted by the Status class.
* Passing false will result in snapshots not being emitted
* @default true
*/
enableSnapshots?: boolean | undefined;
/**
* Optional EventEmitter to be passed in to control the buckets instead of the bucket-interval timer
*/
rotateBucketController?: EventEmitter | undefined;
}
interface Status extends EventEmitter {
stats: Stats;
window: Window;
on(event: "snapshot", listener: (snapshot: Stats) => void): this;
}
interface StatusOptions extends
Pick<
CircuitBreaker.Options,
| "rollingCountBuckets"
| "rollingCountTimeout"
| "rollingPercentilesEnabled"
| "enableSnapshots"
| "rotateBucketController"
>
{
/**
* object of previous stats
*/
stats?: Stats;
}
interface Bucket {
failures: number;
fallbacks: number;
successes: number;
rejects: number;
fires: number;
timeouts: number;
cacheHits: number;
cacheMisses: number;
semaphoreRejections: number;
percentiles: { [percentile: number]: number };
latencyTimes: number[];
}
type Window = Bucket[];
interface Stats extends Bucket {
latencyMean: number;
}
interface State {
name: string;
enabled: boolean;
closed: boolean;
open: boolean;
halfOpen: boolean;
warmUp: boolean;
shutdown: boolean;
lastTimerAt: symbol;
}
/**
* Simple in-memory cache implementation
*/
interface MemoryCache {
/**
* Get cache value by key
* @param {string} key Cache key
* @returns Response from cache
*/
get(key: string): unknown | undefined;
/**
* Set cache key with value and ttl
* @param {string} key Cache key
* @param {any} value Value to cache
* @param {number} ttl Time to live in milliseconds
*/
set(key: string, value: any, ttl: number): void;
/**
* Clear cache
*/
flush(): void;
}
type CacheTransport = MemoryCache;
}
export = CircuitBreaker;