node-circuit-breaker
v1.0.2
Published
Circuit Breaker: Decorators and tools that can easily apply the Circuit Breaker pattern.
Maintainers
Readme
Circuit Breaker
- Decorators and tools that can easily apply the Circuit Breaker pattern.
- Node version >= 16
- Depends on worker thread and BroadcastChannel.
Install
- NPM
$ npm install node-circuit-breaker --save- Yarn
$ yarn add node-circuit-breaker- You may need additional
axios,@nestjs/common, andtypeormpackages to use the Error Wrapper.
API
@CircuitBreaker Method Decorator
- Options
| Member | Sub | Type | Required | Description |
|-----------------------|:-------------|----------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| fallback | | Function string Object | required | An error object to return or a function to run when CircuitBreaker state:OpenFunction : Executes the specified function instead.String : The name of another method within the object in the current context to execute instead.eg) xxxxFallbackObject : Returns the specified value immediately. |
| rules | | Array<CircuitBreakerRule> | required | Rules for determining state:Open |
| | exceptions | Array<typeof Error> | required | Exception list |
| | times | number | required | Number of exceptions within the period |
| | inSeconds | number | required | Period(seconds) for counting exceptions |
| fallbackForSeconds | | number | required | Period(seconds) to respond with fallback before Open -> HalfOpen |
| timeoutMilliSeconds | | number | | If the execution of the method takes longer than the specified time (ms), ExecutionTimeoutError is generated internally. You can use ExecutionTimeoutError in CircuitBreaker rules. |
| scope | | CircuitBreakerScope | | CircuitBreakerScope.DEFAULT : Ignore the context and catch all exceptions raised by the methodCircuitBreakerScope.INSTANCE : Catch only exceptions that occur in methods within instance context |
| onCircuitOpen | | (circuit: Circuit) => Promise<boolean> | | A callback called when state changes to Open. If false is returned, the state is not changed. |
| onCircuitClose | | (circuit: Circuit) => Promise<boolean> | | A callback called when state changes to Closed. If false is returned, the state is not changed. |
| ignore | | (error: any, circuit: Circuit) => Promise<boolean> | | A callback that is called when an error occurs. If true is returned, the error is ignored and the circuit is not affected. |
| onError | | (error: any, circuit: Circuit) => Promise<void> | | A callback that is called when an error occurs. |
CircuitBreakerManager
CircuitBreakerManager.terminate()- Terminate CircuitBreaker Worker. Circuit state change stops.
Usage
class Test {
@CircuitBreaker({
// If state:Open, execute test1Fallback(...) within the same instance.
fallback: 'test1Fallback',
rules: [
// TypeormQueryTimeoutError, RequestTimeoutException, GatewayTimeoutException
// If an error occurs 10 times within 60 seconds, state:Open is set and a fallback is performed.
{
exceptions: [TypeormQueryTimeoutError, RequestTimeoutException, GatewayTimeoutException],
times: 10,
inSeconds: 60
},
// BadGatewayException, TypeormConnectionFailedError, ServiceUnavailableException
// If an error occurs 30 times within 5 seconds, state:Open is set and fallback is performed.
{
exceptions: [BadGatewayException, TypeormConnectionFailedError, ServiceUnavailableException],
times: 30,
inSeconds: 5
}
],
// After state:Open, it becomes state:HalfOpen after 5 seconds, and some calls are performed normally.
// If an error occurs at this time, it changes back to state:Open, and then changes to state:HalfOpen again after 5 seconds.
// If a normal response is made in state:HalfOpen state, it becomes state:Closed state.
fallbackForSeconds: 5,
})
test1(arg: string) {
if (arg === 'error') throw new BadGatewayException();
return arg;
}
test1Fallback(arg: string) {
return 'fallback';
}
@CircuitBreaker({
scope: CircuitBreakerScope.INSTANCE,
fallback: TestFallback.test2,
// If the method takes more than 1000ms to execute, an ExecutionTimeoutError error is generated.
// ExecutionTimeoutError is not thrown, only passed inside the circuit breaker.
timeoutMilliSeconds: 1000,
rules: [
{ exceptions: [BadGatewayException], times: 10, inSeconds: 5 },
{ exceptions: [ExecutionTimeoutError], times: 3, inSeconds: 10 }
],
fallbackForSeconds: 3,
})
test2(arg: string) {
if (arg === 'error') throw new BadGatewayException();
return arg;
}
}
class TestFallback {
static test2(arg: string) {
return arg;
}
}Contributors
Error Wrapper
- Provides error wrappers for frequently used functions.
- The provided Error Wrapper and all kinds of Errors can be caught by
@CircuitBreaker({ rules[].exceptions[...] }).
ExecutionTimeoutError
@CircuitBreaker({...})IftimeoutMilliSecondsis set,ExecutionTimeoutErroroccurs if the execution time of the method is longer than the set time.
TypeORM
- Refines
QueryFailedErroriftypeormis installed. - If the SQL query fails, you can catch the error by identifying whether it is a connection issue or a timeout.
| Source Error | Converted | Condition |
|--------------------|--------------------------------|------------------------------------------------------|
| QueryFailedError | TypeormConnectionFailedError | QueryFailedError.driverError contains connection |
| QueryFailedError | TypeormQueryTimeoutError | QueryFailedError.driverError contains timeout |
Axios -> Nestjs HttpException
- Axios returns an error in the form of
AxiosErrorwhen an error occurs, so it is difficult to use in exception filter. - By converting
AxiosErrorintoHttpExceptionform of Nestjs and using it as a rule of CircuitBreaker, detailed rule setting is possible. - Requires
axios,@nestjs/commonpackages. - Transform rules
