@@ -105,19 +105,37 @@ export default {
105105 _baseUrl ( ) {
106106 return "https://api.createsend.com/api/v3.3" ;
107107 } ,
108- _makeRequest ( opts = { } ) {
108+ async _makeRequest ( opts = { } ) {
109109 const {
110110 $ = this ,
111111 path,
112112 ...otherOpts
113113 } = opts ;
114- return axios ( $ , {
115- ...otherOpts ,
116- url : `${ this . _baseUrl ( ) } ${ path } ` ,
117- headers : {
118- Authorization : `Bearer ${ this . $auth . oauth_access_token } ` ,
119- } ,
120- } ) ;
114+ const requestFn = async ( ) => {
115+ return await axios ( $ , {
116+ ...otherOpts ,
117+ url : `${ this . _baseUrl ( ) } ${ path } ` ,
118+ headers : {
119+ Authorization : `Bearer ${ this . $auth . oauth_access_token } ` ,
120+ } ,
121+ } ) ;
122+ } ;
123+ return await this . retryWithExponentialBackoff ( requestFn ) ;
124+ } ,
125+ // The API has been observed to occasionally return -
126+ // {"Code":120,"Message":"Invalid OAuth Token"}
127+ // Retry if a 401 Unauthorized or 429 (Rate limit exceeded)
128+ // status is returned
129+ async retryWithExponentialBackoff ( requestFn , retries = 3 , backoff = 500 ) {
130+ try {
131+ return await requestFn ( ) ;
132+ } catch ( error ) {
133+ if ( retries > 0 && ( error . response ?. status === 401 || error . response ?. status === 429 ) ) {
134+ await new Promise ( ( resolve ) => setTimeout ( resolve , backoff ) ) ;
135+ return this . retryWithExponentialBackoff ( requestFn , retries - 1 , backoff * 2 ) ;
136+ }
137+ throw error ;
138+ }
121139 } ,
122140 listClients ( opts = { } ) {
123141 return this . _makeRequest ( {
0 commit comments