@@ -28,7 +28,8 @@ export class API {
2828 baseURL : hackmdAPIEndpointURL ,
2929 headers :{
3030 "Content-Type" : "application/json" ,
31- }
31+ } ,
32+ timeout : 30000 , // Increased timeout for low bandwidth
3233 } )
3334
3435 this . axios . interceptors . request . use (
@@ -71,13 +72,48 @@ export class API {
7172 `Received an error response (${ err . response . status } ${ err . response . statusText } ) from HackMD` ,
7273 err . response . status ,
7374 err . response . statusText ,
74- )
75+ ) ;
7576 }
7677 }
77- )
78+ ) ;
7879 }
80+ this . createRetryInterceptor ( this . axios , 3 ) ; // Add retry interceptor with maxRetries = 3
81+ }
82+
83+ // Utility functions for exponential backoff and retry logic
84+ private exponentialBackoff ( retries : number ) : number {
85+ return Math . pow ( 2 , retries ) * 100 ; // Exponential backoff with base delay of 100ms
86+ }
87+
88+ private isRetryableError ( error : AxiosError ) : boolean {
89+ // Retry on network errors, 5xx errors, and rate limiting (429)
90+ return (
91+ ! error . response ||
92+ ( error . response . status >= 500 && error . response . status < 600 ) ||
93+ error . response . status === 429
94+ ) ;
7995 }
8096
97+ // Create retry interceptor function
98+ private createRetryInterceptor ( axiosInstance : AxiosInstance , maxRetries : number ) : void {
99+ let retryCount = 0 ;
100+
101+ axiosInstance . interceptors . response . use (
102+ response => response ,
103+ async error => {
104+ if ( retryCount < maxRetries && this . isRetryableError ( error ) ) {
105+ retryCount ++ ;
106+ const delay = this . exponentialBackoff ( retryCount ) ;
107+ console . warn ( `Retrying request... attempt #${ retryCount } after delay of ${ delay } ms` ) ;
108+ await new Promise ( resolve => setTimeout ( resolve , delay ) ) ;
109+ return axiosInstance ( error . config ) ;
110+ }
111+
112+ retryCount = 0 ; // Reset retry count after a successful request
113+ return Promise . reject ( error ) ;
114+ }
115+ ) ;
116+ }
81117 async getMe < Opt extends RequestOptions > ( options = defaultOption as Opt ) : Promise < OptionReturnType < Opt , GetMe > > {
82118 return this . unwrapData ( this . axios . get < GetMe > ( "me" ) , options . unwrapData ) as unknown as OptionReturnType < Opt , GetMe >
83119 }
0 commit comments