@@ -28,7 +28,8 @@ export class API {
28
28
baseURL : hackmdAPIEndpointURL ,
29
29
headers :{
30
30
"Content-Type" : "application/json" ,
31
- }
31
+ } ,
32
+ timeout : 30000 , // Increased timeout for low bandwidth
32
33
} )
33
34
34
35
this . axios . interceptors . request . use (
@@ -71,13 +72,48 @@ export class API {
71
72
`Received an error response (${ err . response . status } ${ err . response . statusText } ) from HackMD` ,
72
73
err . response . status ,
73
74
err . response . statusText ,
74
- )
75
+ ) ;
75
76
}
76
77
}
77
- )
78
+ ) ;
78
79
}
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
+ ) ;
79
95
}
80
96
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
+ }
81
117
async getMe < Opt extends RequestOptions > ( options = defaultOption as Opt ) : Promise < OptionReturnType < Opt , GetMe > > {
82
118
return this . unwrapData ( this . axios . get < GetMe > ( "me" ) , options . unwrapData ) as unknown as OptionReturnType < Opt , GetMe >
83
119
}
0 commit comments