Skip to content

Commit

Permalink
feat: add enableRetries and disableRetries
Browse files Browse the repository at this point in the history
  • Loading branch information
Barrett Schonefeld committed Aug 23, 2021
1 parent ed982e3 commit 3c29f51
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 6 deletions.
20 changes: 18 additions & 2 deletions lib/base-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { OutgoingHttpHeaders } from 'http';
import { AuthenticatorInterface, checkCredentials, readExternalSources } from '../auth';
import { stripTrailingSlash } from './helper';
import logger from './logger';
import { RequestWrapper } from './request-wrapper';
import { RequestWrapper, RetryOptions } from './request-wrapper';

/**
* Configuration values for a service.
Expand Down Expand Up @@ -65,7 +65,7 @@ export class BaseService {

private authenticator: AuthenticatorInterface;

private requestWrapperInstance;
private requestWrapperInstance: RequestWrapper;

/**
* Configuration values for a service.
Expand Down Expand Up @@ -170,6 +170,22 @@ export class BaseService {
return this.requestWrapperInstance.getHttpClient();
}

/**
* Enable retries for unfulfilled requests.
*
* @param {Map<string, number>} retryConfig configuration for retries
*/
public enableRetries(retryConfig?: RetryOptions) {
return this.requestWrapperInstance.enableRetries(retryConfig);
}

/**
* Disables retries.
*/
public disableRetries() {
return this.requestWrapperInstance.disableRetries();
}

/**
* Configure the service using external configuration
*
Expand Down
64 changes: 60 additions & 4 deletions lib/request-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
* limitations under the License.
*/

import axios, { AxiosRequestConfig } from 'axios';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import * as rax from 'retry-axios';

import axiosCookieJarSupport from 'axios-cookiejar-support';
import extend = require('extend');
Expand All @@ -36,10 +37,29 @@ import {
import logger from './logger';
import { streamToPromise } from './stream-to-promise';

/**
* Retry configuration options.
*/
export interface RetryOptions {
/**
* Maximum retries to attempt.
*/
maxRetries?: number;

/**
* Ceiling for the retry delay (in ms) - delay will not exceed this value.
*/
maxRetryInterval?: number;
}

export class RequestWrapper {
private axiosInstance;
private axiosInstance: AxiosInstance;

private compressRequestData: boolean;
private retryInterceptorId: number;

private retryConfig: rax.RetryConfig;

public compressRequestData: boolean;

constructor(axiosOptions?) {
axiosOptions = axiosOptions || {};
Expand Down Expand Up @@ -240,6 +260,7 @@ export class RequestWrapper {
headers,
params: qs,
data,
raxConfig: this.retryConfig ?? this.retryConfig,
responseType: options.responseType || 'json',
paramsSerializer: (params) => querystring.stringify(params),
};
Expand All @@ -257,7 +278,8 @@ export class RequestWrapper {
delete res.request;

// the other sdks use the interface `result` for the body
res.result = res.data;
// eslint-disable-next-line @typescript-eslint/dot-notation
res['result'] = res.data;
delete res.data;

// return another promise that resolves with 'res' to be handled in generated code
Expand Down Expand Up @@ -346,6 +368,40 @@ export class RequestWrapper {
return this.axiosInstance;
}

private static getRetryConfig(
axiosInstance: AxiosInstance,
retryConfig?: RetryOptions
): rax.RetryConfig {
const config: rax.RetryConfig = {
instance: axiosInstance,
backoffType: 'exponential',
checkRetryAfter: true,
};
if (retryConfig) {
if (typeof retryConfig.maxRetries === 'number') {
config.retry = retryConfig.maxRetries;
}
if (typeof retryConfig.maxRetryInterval === 'number') {
config.maxRetryDelay = retryConfig.maxRetryInterval;
}
}
return config;
}

public enableRetries(retryConfig?: RetryOptions) {
this.axiosInstance.defaults.raxConfig = {
instance: this.axiosInstance,
};
this.retryConfig = RequestWrapper.getRetryConfig(this.axiosInstance, retryConfig);
this.retryInterceptorId = rax.attach(this.axiosInstance);
}

public disableRetries() {
if (this.retryInterceptorId) {
rax.detach(this.retryInterceptorId, this.axiosInstance);
}
}

private async gzipRequestBody(data: any, headers: OutgoingHttpHeaders): Promise<Buffer | any> {
// skip compression if user has set the encoding header to gzip
const contentSetToGzip =
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"mime-types": "~2.1.18",
"object.omit": "~3.0.0",
"object.pick": "~1.3.0",
"retry-axios": "^2.6.0",
"semver": "^6.2.0",
"tough-cookie": "^4.0.0"
},
Expand Down

0 comments on commit 3c29f51

Please sign in to comment.