Files
skywatch/server/circuitBreaker.js
nmemmert db85573986 feat: Add real-time notification center with WebSocket integration
- Add in-app notification system with database storage
- Implement bell icon component with unread count badge in dashboard header
- Add full Notifications page tab with pagination and filtering (All/Unread/Read)
- Implement real-time WebSocket push notifications to all connected clients
- Add notification API endpoints: GET, PUT /read, DELETE, POST /clear
- Fix critical bug in notificationService where 'status' variable was undefined
- Add Notifications route to App.js routing
- Enhanced UI with notification popup in header and dedicated full-page view
- Auto-reconnect WebSocket with 5s timeout on disconnect
- Support rich notification content with resource details and timestamps
2026-01-14 14:51:29 -05:00

63 lines
1.4 KiB
JavaScript

// Circuit breaker implementation for API resilience
class CircuitBreaker {
constructor(failureThreshold = 5, resetTimeout = 60000, errorFilter = null) {
this.failureThreshold = failureThreshold;
this.resetTimeout = resetTimeout;
this.errorFilter = errorFilter;
this.failureCount = 0;
this.lastFailureTime = null;
this.state = 'closed'; // closed, open, half-open
}
async execute(fn, fallback = null) {
if (this.state === 'open') {
if (Date.now() - this.lastFailureTime > this.resetTimeout) {
this.state = 'half-open';
} else {
if (fallback) return fallback();
throw new Error('Circuit breaker is open');
}
}
try {
const result = await fn();
if (this.state === 'half-open') {
this.close();
}
return result;
} catch (error) {
if (this.errorFilter && !this.errorFilter(error)) {
throw error;
}
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.failureThreshold) {
this.open();
}
throw error;
}
}
close() {
this.failureCount = 0;
this.state = 'closed';
}
open() {
this.state = 'open';
}
getState() {
return {
state: this.state,
failureCount: this.failureCount,
lastFailureTime: this.lastFailureTime
};
}
}
module.exports = CircuitBreaker;