cachly
Version:
Type-safe, production-ready in-memory cache system for Node.js and TypeScript with advanced features.
98 lines • 3.01 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CircuitBreaker = void 0;
class CircuitBreaker {
constructor(config) {
this.failureCount = 0;
this.monitorWindow = [];
this.config = config;
this.state = {
state: 'closed',
failureCount: 0,
lastFailureTime: 0,
nextAttemptTime: 0,
};
}
async execute(key, operation, fallback) {
if (!this.config.enabled) {
return operation();
}
if (this.state.state === 'open') {
if (Date.now() < this.state.nextAttemptTime) {
if (fallback) {
return fallback(key);
}
throw new Error(`Circuit breaker is open for key: ${key}`);
}
this.state.state = 'half-open';
}
try {
const result = await operation();
this.onSuccess();
return result;
}
catch (error) {
this.onFailure();
if (fallback) {
return fallback(key);
}
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state.failureCount = 0;
this.state.state = 'closed';
this.monitorWindow = [];
}
onFailure() {
const now = Date.now();
this.failureCount++;
this.state.failureCount = this.failureCount;
this.state.lastFailureTime = now;
// Add to monitoring window
this.monitorWindow.push(now);
// Remove old entries from monitoring window
const windowSize = this.config.monitorWindow || 60000; // 1 minute default
this.monitorWindow = this.monitorWindow.filter(time => now - time < windowSize);
if (this.failureCount >= this.config.failureThreshold) {
this.state.state = 'open';
this.state.nextAttemptTime = now + this.config.recoveryTimeout;
}
}
getState() {
return { ...this.state };
}
isOpen() {
return this.state.state === 'open';
}
isHalfOpen() {
return this.state.state === 'half-open';
}
isClosed() {
return this.state.state === 'closed';
}
getFailureCount() {
return this.failureCount;
}
reset() {
this.failureCount = 0;
this.state = {
state: 'closed',
failureCount: 0,
lastFailureTime: 0,
nextAttemptTime: 0,
};
this.monitorWindow = [];
}
getFailureRate() {
if (this.monitorWindow.length === 0)
return 0;
const now = Date.now();
const windowSize = this.config.monitorWindow || 60000;
const recentFailures = this.monitorWindow.filter(time => now - time < windowSize).length;
return recentFailures / this.monitorWindow.length;
}
}
exports.CircuitBreaker = CircuitBreaker;
//# sourceMappingURL=CircuitBreaker.js.map