import { AxiosInstance } from 'axios' ; import { HttpLogEvents } from '../../../../../tracing/LogEvents' ; import { HttpRetryLogFields } from '../../../../../tracing/LogFields' ; import { isAbortedOrNetworkErrorOrRouterTimeout } from '../../../../../utils/retry' ; import { RequestConfig } from '../../../../typings' ; import { TraceableRequestConfig } from '../../../tracing' ; function fixConfig ( axiosInstance , config ) { if ( axiosInstance . defaults . httpAgent === config . httpAgent ) { delete config . httpAgent ; } if ( axiosInstance . defaults . httpsAgent === config . httpsAgent ) { delete config . httpsAgent ; } } const exponentialDelay = ( initialBackoffDelay , exponentialBackoffCoefficient , retryNumber ) => { const delay = initialBackoffDelay * Math . pow ( exponentialBackoffCoefficient , retryNumber - 1 ) ; const randomSum = delay * 0.2 * Math . random ( ) ; return delay + randomSum ; } ; const onResponseError = ( http ) => ( error ) => { if ( error . config == null ) { return Promise . reject ( error ) ; } const config = error . config as RequestConfig ; if ( config . retries == null || config . retries === 0 ) { return Promise . reject ( error ) ; } const { initialBackoffDelay = 200 , exponentialBackoffCoefficient = 2 , exponentialTimeoutCoefficient , } = config ; const retryCount = config . retryCount || 0 ; const shouldRetry = isAbortedOrNetworkErrorOrRouterTimeout ( error ) && retryCount < config . retries ; if ( shouldRetry ) { config . retryCount = retryCount + 1 ; const delay = exponentialDelay ( initialBackoffDelay , exponentialBackoffCoefficient , config . retryCount ) ; fixConfig ( http , config ) ; config . timeout = exponentialTimeoutCoefficient ? ( config . timeout as number ) * exponentialTimeoutCoefficient : config . timeout ; config . transformRequest = [ data => data ] ; config . tracing ! . rootSpan ! . log ( { event : HttpLogEvents . SETUP_REQUEST_RETRY , [ HttpRetryLogFields . RETRY_NUMBER ] : config . retryCount , [ HttpRetryLogFields . RETRY_IN ] : delay } ) ; return new Promise ( resolve => setTimeout ( ( ) => resolve ( http ( config ) ) , delay ) ) ; } return Promise . reject ( error ) ; } ; export const addExponentialBackoffResponseInterceptor = ( http ) => { http . interceptors . response . use ( undefined , onResponseError ( http ) ) ; } ;