@@ -11,24 +11,14 @@ interface EndpointState {
1111 lastFailureTime : Date ;
1212}
1313
14- interface CircuitBreakerState {
15- isOpen : boolean ;
16- lastFailureTime : Date ;
17- consecutiveFailures : number ;
18- nextRetryTime : Date ;
19- }
20-
2114export class EndpointProvider {
2215 private static instance : EndpointProvider ;
2316 private endpoints : NetworkEndpoints ;
2417 private currentIndex : Record < string , number > = { } ;
2518 private endpointStates : Map < string , EndpointState > = new Map ( ) ;
2619 private lastEndpointUsed : Record < string , string > = { } ;
27- private circuitBreakers : Map < string , CircuitBreakerState > = new Map ( ) ;
2820
29- // Circuit breaker configuration
30- private readonly CIRCUIT_BREAKER_BASE_DELAY = 30000 ; // 30 seconds base delay
31- private readonly CIRCUIT_BREAKER_MAX_DELAY = 300000 ; // 5 minutes max delay
21+ // Endpoint retry configuration
3222 private readonly ENDPOINT_RETRY_DELAY = 60000 ; // 1 minute before retrying a failed endpoint
3323
3424 private constructor ( ) {
@@ -40,14 +30,6 @@ export class EndpointProvider {
4030 this . currentIndex [ network ] = 0 ;
4131 this . lastEndpointUsed [ network ] = '' ;
4232
43- // Initialize circuit breaker state
44- this . circuitBreakers . set ( network , {
45- isOpen : false ,
46- lastFailureTime : new Date ( 0 ) ,
47- consecutiveFailures : 0 ,
48- nextRetryTime : new Date ( 0 )
49- } ) ;
50-
5133 // Initialize endpoint states
5234 this . endpoints [ network ] . forEach ( endpoint => {
5335 this . endpointStates . set ( endpoint , {
@@ -73,13 +55,6 @@ export class EndpointProvider {
7355 throw new Error ( `No endpoints configured for network: ${ network } ` ) ;
7456 }
7557
76- // Check circuit breaker
77- const circuitBreaker = this . circuitBreakers . get ( network ) ;
78- if ( circuitBreaker ?. isOpen && new Date ( ) < circuitBreaker . nextRetryTime ) {
79- const remainingTime = Math . ceil ( ( circuitBreaker . nextRetryTime . getTime ( ) - Date . now ( ) ) / 1000 ) ;
80- throw new Error ( `Circuit breaker open for ${ network } , retry in ${ remainingTime } s` ) ;
81- }
82-
8358 // Get available (non-blacklisted or recently failed) endpoints
8459 const now = new Date ( ) ;
8560 const availableEndpoints = networkEndpoints . filter ( endpoint => {
@@ -94,31 +69,21 @@ export class EndpointProvider {
9469 return timeSinceFailure > this . ENDPOINT_RETRY_DELAY ;
9570 } ) ;
9671
97- // If all endpoints are still failing, check if we should open circuit breaker
72+ // If all endpoints are still failing, try the oldest failed endpoint
9873 if ( availableEndpoints . length === 0 ) {
99- this . handleAllEndpointsFailed ( network ) ;
100-
101- // Try to find the oldest failed endpoint to retry
10274 const oldestFailure = this . findOldestFailedEndpoint ( network ) ;
10375 if ( oldestFailure ) {
10476 this . resetEndpointState ( oldestFailure ) ;
105- console . log ( `Circuit breaker: Retrying oldest failed endpoint: ${ oldestFailure } ` ) ;
77+ console . log ( `All endpoints failed, retrying oldest failed endpoint: ${ oldestFailure } ` ) ;
10678 return oldestFailure ;
10779 }
10880
10981 // Last resort: clear all blacklists and use first endpoint
110- console . warn ( `Circuit breaker: All endpoints exhausted for ${ network } , clearing blacklists` ) ;
82+ console . warn ( `All endpoints exhausted for ${ network } , clearing blacklists` ) ;
11183 this . clearBlacklist ( network ) ;
11284 return networkEndpoints [ 0 ] ;
11385 }
11486
115- // Reset circuit breaker if we have available endpoints
116- if ( circuitBreaker ?. isOpen ) {
117- console . log ( `Circuit breaker: Endpoints recovered for ${ network } , closing circuit breaker` ) ;
118- circuitBreaker . isOpen = false ;
119- circuitBreaker . consecutiveFailures = 0 ;
120- }
121-
12287 // Smart endpoint selection: avoid recently used endpoints if possible
12388 let selectedEndpoint : string ;
12489
@@ -163,42 +128,6 @@ export class EndpointProvider {
163128 state . lastUsed = new Date ( ) ;
164129 console . warn ( `Blacklisted endpoint for session: ${ endpoint } (failure count: ${ state . failureCount } )` ) ;
165130 }
166-
167- // Check if this triggers circuit breaker
168- this . checkCircuitBreaker ( network ) ;
169- }
170-
171- private handleAllEndpointsFailed ( network : string ) : void {
172- const circuitBreaker = this . circuitBreakers . get ( network ) ;
173- if ( ! circuitBreaker ) return ;
174-
175- circuitBreaker . consecutiveFailures ++ ;
176- circuitBreaker . lastFailureTime = new Date ( ) ;
177-
178- // Calculate exponential backoff delay
179- const baseDelay = this . CIRCUIT_BREAKER_BASE_DELAY ;
180- const exponentialDelay = Math . min (
181- baseDelay * Math . pow ( 2 , circuitBreaker . consecutiveFailures - 1 ) ,
182- this . CIRCUIT_BREAKER_MAX_DELAY
183- ) ;
184-
185- circuitBreaker . nextRetryTime = new Date ( Date . now ( ) + exponentialDelay ) ;
186- circuitBreaker . isOpen = true ;
187-
188- console . warn ( `Circuit breaker opened for ${ network } : retry in ${ Math . ceil ( exponentialDelay / 1000 ) } s (attempt ${ circuitBreaker . consecutiveFailures } )` ) ;
189- }
190-
191- private checkCircuitBreaker ( network : string ) : void {
192- const networkEndpoints = this . endpoints [ network ] || [ ] ;
193- const allBlacklisted = networkEndpoints . every ( endpoint => {
194- const state = this . endpointStates . get ( endpoint ) ;
195- return state ?. isBlacklisted ;
196- } ) ;
197-
198- if ( allBlacklisted ) {
199- console . warn ( `All endpoints blacklisted for ${ network } , considering circuit breaker` ) ;
200- this . handleAllEndpointsFailed ( network ) ;
201- }
202131 }
203132
204133 private findOldestFailedEndpoint ( network : string ) : string | null {
@@ -237,27 +166,12 @@ export class EndpointProvider {
237166 state . lastUsed = new Date ( 0 ) ;
238167 }
239168 } ) ;
240-
241- // Reset circuit breaker
242- const circuitBreaker = this . circuitBreakers . get ( network ) ;
243- if ( circuitBreaker ) {
244- circuitBreaker . isOpen = false ;
245- circuitBreaker . consecutiveFailures = 0 ;
246- circuitBreaker . nextRetryTime = new Date ( 0 ) ;
247- }
248169 } else {
249170 // Clear all blacklisted endpoints
250171 this . endpointStates . forEach ( state => {
251172 state . isBlacklisted = false ;
252173 state . lastUsed = new Date ( 0 ) ;
253174 } ) ;
254-
255- // Reset all circuit breakers
256- this . circuitBreakers . forEach ( circuitBreaker => {
257- circuitBreaker . isOpen = false ;
258- circuitBreaker . consecutiveFailures = 0 ;
259- circuitBreaker . nextRetryTime = new Date ( 0 ) ;
260- } ) ;
261175 }
262176 }
263177
@@ -266,11 +180,6 @@ export class EndpointProvider {
266180 available : number ;
267181 blacklisted : string [ ] ;
268182 endpointDetails : Record < string , { failureCount : number ; lastUsed : string ; isBlacklisted : boolean } > ;
269- circuitBreaker : {
270- isOpen : boolean ;
271- consecutiveFailures : number ;
272- nextRetryTime : string ;
273- } ;
274183 } {
275184 const networkEndpoints = this . endpoints [ network ] || [ ] ;
276185 const blacklisted = networkEndpoints . filter ( endpoint => {
@@ -288,18 +197,11 @@ export class EndpointProvider {
288197 } ;
289198 } ) ;
290199
291- const circuitBreaker = this . circuitBreakers . get ( network ) ;
292-
293200 return {
294201 total : networkEndpoints . length ,
295202 available : networkEndpoints . length - blacklisted . length ,
296203 blacklisted,
297- endpointDetails,
298- circuitBreaker : {
299- isOpen : circuitBreaker ?. isOpen || false ,
300- consecutiveFailures : circuitBreaker ?. consecutiveFailures || 0 ,
301- nextRetryTime : circuitBreaker ?. nextRetryTime . toISOString ( ) || 'never'
302- }
204+ endpointDetails
303205 } ;
304206 }
305207}
0 commit comments