Skip to content

Commit

Permalink
extend retries for deployment status polling
Browse files Browse the repository at this point in the history
  • Loading branch information
maorb-dev committed Jan 25, 2024
1 parent ce5291e commit ba719d6
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 10 deletions.
34 changes: 26 additions & 8 deletions src/services/api-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import crypto from 'node:crypto';
import https from 'node:https';

import axios, { AxiosError } from 'axios';
import { default as axiosRetry, isIdempotentRequestError, isNetworkError } from 'axios-retry';
import {
IAxiosRetryConfig,
default as axiosRetry,
exponentialDelay,
isNetworkOrIdempotentRequestError,
} from 'axios-retry';
import { ZodObject } from 'zod/lib/types';

import { CONFIG_KEYS } from 'consts/config';
Expand All @@ -16,15 +21,26 @@ import logger from 'utils/logger';

const DEFAULT_TIMEOUT = 10 * 1000;

axiosRetry(axios, {
retries: 5, // number of retries
retryDelay: retryCount => retryCount * 1000,
/**
* Our default retry policy for axios-retry
* @see https://github.com/softonic/axios-retry?tab=readme-ov-file#usage
* shouldResetTimeout: if true, does not fail the entire process based on the time passed from the original request, but rather applies the timeout to each retry individually
* retryDelay: exponential delay with jitter, minimum 1 second before the 1st retry
* retryCondition: retry if network error (excluding CANCELED and ABORTED) or 5xx error on idempotent or safe requests (GET, HEAD, OPTIONS, PUT, DELETE)
*/
const DEFAULT_RETRY_POLICY: IAxiosRetryConfig = {
shouldResetTimeout: false,
retries: 3,
retryDelay: (...arg) => exponentialDelay(...arg, 1000),
retryCondition: error => {
const retriableStatusCodes = [500, 502, 503, 504];
const isRetriableStatusCode = error.response && retriableStatusCodes.includes(error.response.status);
return isRetriableStatusCode || isNetworkError(error) || isIdempotentRequestError(error);
return isNetworkOrIdempotentRequestError(error);
},
});
};

const configureRetryPolicy = (customPolicy: IAxiosRetryConfig): void => {
const retryPolicy = { ...DEFAULT_RETRY_POLICY, ...customPolicy };
axiosRetry(axios, retryPolicy);
};

const validateResponseIfError = (response: object, schemaValidator?: ZodObject<any>): object => {
if (schemaValidator) {
Expand Down Expand Up @@ -70,8 +86,10 @@ const handleErrors = (error: any | Error | AxiosError): never => {
export async function execute<T extends BaseResponseHttpMetaData>(
params: ExecuteParams,
schemaValidator?: ZodObject<any>,
retryPolicy: IAxiosRetryConfig = {},
): Promise<T> {
const DEBUG_TAG = 'api_service';
configureRetryPolicy(retryPolicy);
const accessToken = ConfigService.getConfigDataByKey(CONFIG_KEYS.ACCESS_TOKEN);
if (!accessToken) {
logger.error(ACCESS_TOKEN_NOT_FOUND);
Expand Down
5 changes: 3 additions & 2 deletions src/services/push-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const uploadClientZipFile = async (appVersionId: number, buffer: Buffer)
return response.data;
};

export const getAppVersionDeploymentStatus = async (appVersionId: number) => {
export const getAppVersionDeploymentStatus = async (appVersionId: number, extendedRetryPolicy: boolean = false) => {
try {
const baseAppVersionIdStatusUrl = getAppVersionDeploymentStatusUrl(appVersionId);
const url = appsUrlBuilder(baseAppVersionIdStatusUrl);
Expand All @@ -79,6 +79,7 @@ export const getAppVersionDeploymentStatus = async (appVersionId: number) => {
method: HttpMethodTypes.GET,
},
appVersionDeploymentStatusSchema,
extendedRetryPolicy ? { shouldResetTimeout: true, retries: 6 } : undefined,
);
return response;
} catch (error_: any | HttpError) {
Expand Down Expand Up @@ -107,7 +108,7 @@ export const pollForDeploymentStatus = async (
DeploymentStatusTypesSchema['building-app'],
DeploymentStatusTypesSchema['deploying-app'],
];
const response = await getAppVersionDeploymentStatus(appVersionId);
const response = await getAppVersionDeploymentStatus(appVersionId, true);
if (statusesToKeepPolling.includes(response.status)) {
if (progressLogger) {
progressLogger(response.status, response.tip);
Expand Down

0 comments on commit ba719d6

Please sign in to comment.