@@ -7,6 +7,8 @@ const apiRequest = client => {
77 const getAuth = require ( './get-auth' ) ( client )
88 // delete no more valid authentications
99 const deleteAuth = require ( './delete-auth' ) ( client )
10+ // handle access token refresh
11+ const refreshToken = require ( './refresh-token' ) ( client )
1012
1113 // count per store running request
1214 // prevent rate limit error
@@ -33,6 +35,15 @@ const apiRequest = client => {
3335 options . accessToken = accessToken
3436 }
3537
38+ // fallback dealing with out of date tokens
39+ let isRefreshingToken = false
40+ const askRefreshToken = ( ) => {
41+ if ( ! isRefreshingToken ) {
42+ refreshToken ( storeId , myId ) . catch ( console . error )
43+ isRefreshingToken = true
44+ }
45+ }
46+
3647 // send HTTP request
3748 let retries = 0
3849 const send = ( ) => {
@@ -89,32 +100,41 @@ const apiRequest = client => {
89100 return retry ( 8500 , error )
90101 }
91102
92- if ( status === 401 && authenticated && auth . row && config ) {
103+ if ( status === 401 && authenticated ) {
93104 // authentication error
94- // not authorized by auth scope ?
95- // mark returned error object
96- error . appErrorLog = true
97-
98- // try to log error on app hidden data
99- ecomClient . store ( {
100- ...options ,
101- url : '/applications/' + auth . row . application_id + '/hidden_data.json' ,
102- method : 'PATCH' ,
103- data : {
104- last_api_error : {
105- url : config . url ,
106- method : config . method ,
107- response : data
105+ if ( data && data . error_code === 132 && ! retries ) {
106+ // "Token was valid, but expired"
107+ const delayMs = isRefreshingToken ? 2500 : 8500
108+ askRefreshToken ( )
109+ return retry ( delayMs , error )
110+ }
111+
112+ if ( auth . row && config ) {
113+ // not authorized by auth scope ?
114+ // mark returned error object
115+ error . appErrorLog = true
116+
117+ // try to log error on app hidden data
118+ ecomClient . store ( {
119+ ...options ,
120+ url : '/applications/' + auth . row . application_id + '/hidden_data.json' ,
121+ method : 'PATCH' ,
122+ data : {
123+ last_api_error : {
124+ url : config . url ,
125+ method : config . method ,
126+ response : data
127+ }
108128 }
109- }
110- } ) . then ( ( ) => {
111- error . appErrorLogged = true
112- reject ( error )
113- } ) . catch ( err => {
114- error . appErrorLog = err
115- reject ( error )
116- } )
117- return
129+ } ) . then ( ( ) => {
130+ error . appErrorLogged = true
131+ reject ( error )
132+ } ) . catch ( err => {
133+ error . appErrorLog = err
134+ reject ( error )
135+ } )
136+ return
137+ }
118138 }
119139 } else if ( ! retries ) {
120140 // timeout?
@@ -132,15 +152,27 @@ const apiRequest = client => {
132152 send ( )
133153 } else {
134154 // control requests with delay
155+ let delayMs
135156 let delayFactor = running [ storeId ]
136157 if ( typeof delayFactor !== 'number' ) {
158+ // first concurrent request with this store
137159 running [ storeId ] = delayFactor = 0
160+ if ( auth . row && auth . row . expires ) {
161+ const tokenTimestamp = new Date ( auth . row . expires ) . getTime ( )
162+ if ( tokenTimestamp <= Date . now ( ) + 1000 * 60 * 10 ) {
163+ // send token update request in advance
164+ askRefreshToken ( )
165+ if ( tokenTimestamp <= Date . now ( ) + 1000 * 5 ) {
166+ delayMs = 6000
167+ }
168+ }
169+ }
138170 }
139171 running [ storeId ] ++
140172 setTimeout ( ( ) => {
141173 running [ storeId ] --
142174 send ( )
143- } , delayFactor * 200 )
175+ } , delayMs || delayFactor * 200 )
144176 }
145177 }
146178
0 commit comments