WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
at atb-52-css-token-extraction 74 lines 2.0 kB view raw
1import type { Logger } from "@atbb/logger"; 2 3/** 4 * Implements circuit breaker pattern to prevent cascading failures. 5 * 6 * Tracks consecutive errors and triggers a callback when threshold is exceeded. 7 * This prevents the system from repeatedly attempting operations that are likely 8 * to fail, allowing for graceful degradation. 9 */ 10export class CircuitBreaker { 11 private consecutiveFailures = 0; 12 13 /** 14 * @param maxFailures - Maximum consecutive failures before circuit breaks 15 * @param onBreak - Callback invoked when circuit breaks 16 */ 17 constructor( 18 private maxFailures: number, 19 private onBreak: () => Promise<void>, 20 private logger: Logger 21 ) {} 22 23 /** 24 * Execute an operation with circuit breaker protection 25 * 26 * @param operation - The async operation to execute 27 * @param operationName - Name for logging purposes 28 */ 29 async execute<T>( 30 operation: () => Promise<T>, 31 operationName: string 32 ): Promise<void> { 33 try { 34 await operation(); 35 this.reset(); 36 } catch (error) { 37 await this.recordFailure(operationName, error); 38 } 39 } 40 41 /** 42 * Record a failure and check if circuit should break 43 */ 44 private async recordFailure(operationName: string, error: unknown): Promise<void> { 45 this.consecutiveFailures++; 46 this.logger.error("Circuit breaker failure", { 47 operationName, 48 consecutiveFailures: this.consecutiveFailures, 49 maxFailures: this.maxFailures, 50 error: error instanceof Error ? error.message : String(error), 51 }); 52 53 if (this.consecutiveFailures >= this.maxFailures) { 54 this.logger.error("Circuit breaker tripped - max consecutive failures reached", { 55 maxFailures: this.maxFailures, 56 }); 57 await this.onBreak(); 58 } 59 } 60 61 /** 62 * Reset the failure counter (call on successful operation) 63 */ 64 reset(): void { 65 this.consecutiveFailures = 0; 66 } 67 68 /** 69 * Get current failure count for monitoring 70 */ 71 getFailureCount(): number { 72 return this.consecutiveFailures; 73 } 74}