@gravityforms/gulp-tasks
Version:
Configurable Gulp tasks for use in Gravity Forms projects.
51 lines (43 loc) • 1.94 kB
JavaScript
/**
* @description Generic async retry utility with exponential backoff.
* Reads the retry count from the GITHUB_RETRY_COUNT environment variable,
* falling back to a configurable default (3).
*
* @since 8.2.5
*
* @param {Function} fn Async function to retry.
* @param {Object} options Retry options.
* @param {string} options.label Human-readable label for log/error messages (e.g. "push tag").
* @param {number} [options.retries] Override retry count (defaults to GITHUB_RETRY_COUNT or 3).
* @param {number} [options.baseDelayMs] Base delay in ms before exponential increase (default 1000).
*
* @return {Promise<*>} The resolved value from the async function.
*/
const withRetry = async ( fn, { label, retries, baseDelayMs = 1000 } = {} ) => {
const maxRetries = retries || parseInt( process.env.GITHUB_RETRY_COUNT, 10 ) || 3;
let lastError;
for ( let attempt = 1; attempt <= maxRetries; attempt++ ) {
try {
return await fn();
} catch ( error ) {
lastError = error;
if ( attempt < maxRetries ) {
const delay = Math.pow( attempt, 2 ) * baseDelayMs;
const statusInfo = error.status ? ` (${ error.status })` : '';
console.warn(
`Attempt ${ attempt }/${ maxRetries } for "${ label }" failed${ statusInfo }. Retrying in ${ delay / 1000 }s...`,
);
await new Promise( ( resolve ) => setTimeout( resolve, delay ) );
}
}
}
const statusInfo = lastError.status ? ` (${ lastError.status })` : '';
const readableMessage = `${ label } failed after ${ maxRetries } attempts${ statusInfo }. ` +
`The final error was: ${ lastError.message }. ` +
'This is typically caused by temporary GitHub instability — re-running the build may resolve it.';
const retryError = new Error( readableMessage );
retryError.originalError = lastError;
retryError.attempts = maxRetries;
throw retryError;
};
export default withRetry;