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
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}