jssafecircuit
Version:
A Node.js library implementing a circuit breaker pattern to manage and mitigate failures in asynchronous operations, with configurable states and callback events.
105 lines (87 loc) • 2.4 kB
JavaScript
const { EventEmitter } = require('events');
const CircuitBreakerState = {
CLOSED: 'closed',
OPEN: 'open',
HALF_OPEN: 'half_open'
};
class CircuitBreaker extends EventEmitter {
constructor(maxFailures, timeout, pauseTime, maxConsecutiveSuccesses) {
super();
this.state = CircuitBreakerState.CLOSED;
this.consecutiveFailures = 0;
this.totalFailures = 0;
this.totalSuccesses = 0;
this.maxFailures = maxFailures;
this.timeout = timeout;
this.openTimeout = new Date(0);
this.pauseTime = pauseTime;
this.consecutiveSuccesses = 0;
this.maxConsecutiveSuccesses = maxConsecutiveSuccesses;
}
execute(fn) {
return new Promise(async (resolve, reject) => {
const executeFunction = async () => {
try {
const result = await fn();
this.handleSuccess();
resolve(result);
} catch (error) {
this.handleFailure();
reject(error);
}
};
switch (this.state) {
case CircuitBreakerState.OPEN:
if (new Date() > this.openTimeout) {
this.state = CircuitBreakerState.HALF_OPEN;
this.emit('halfOpen');
} else {
return reject(new Error("circuit breaker is open"));
}
break;
case CircuitBreakerState.HALF_OPEN:
await executeFunction();
await this.delay(this.pauseTime);
return;
}
await executeFunction();
});
}
handleFailure() {
this.consecutiveFailures += 1;
this.totalFailures += 1;
if (this.consecutiveFailures >= this.maxFailures) {
this.trip();
}
}
handleSuccess() {
this.reset();
this.totalSuccesses += 1;
}
trip() {
this.state = CircuitBreakerState.OPEN;
this.consecutiveFailures = 0;
this.consecutiveSuccesses = 0;
this.openTimeout = new Date(Date.now() + this.timeout * 1000);
this.emit('open');
}
reset() {
this.state = CircuitBreakerState.CLOSED;
this.consecutiveFailures = 0;
this.consecutiveSuccesses = 0;
this.emit('close');
}
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
setOnOpen(callback) {
this.on('open', callback);
}
setOnClose(callback) {
this.on('close', callback);
}
setOnHalfOpen(callback) {
this.on('halfOpen', callback);
}
}
module.exports = CircuitBreaker;