Relocate statics below constructor

This commit is contained in:
2026-07-18 13:53:04 +00:00
parent 873a075329
commit 798ccdf32c

View File

@@ -10,6 +10,31 @@ import { ExponentialBackoffStoppedRetriesError, ExponentialBackoffMaxRetriesHitE
* The growth rate is the factor by which the delay increases with each attempt. * The growth rate is the factor by which the delay increases with each attempt.
*/ */
export class ExponentialBackoff { export class ExponentialBackoff {
private readonly options: ExponentialBackoffOptions;
/**
* Creates a new exponential-backoff instance.
*
* Unspecified options use the defaults listed below.
*
* @param options - Exponential-backoff configuration overrides.
* @param options.maxDelay - Maximum delay between retries. Default: `10_000` ms.
* @param options.maxAttempts - Maximum number of attempts; `0` retries indefinitely. Default: `10`.
* @param options.baseDelay - Delay used as the basis for the first retry. Default: `1_000` ms.
* @param options.growthRate - Multiplier applied to the delay after each attempt. Default: `2`.
* @param options.jitter - Maximum proportional reduction subtracted from each delay (01). Default: `0.1`.
*/
constructor(options: Partial<ExponentialBackoffOptions> = {}) {
this.options = {
maxDelay: 10_000,
maxAttempts: 10,
baseDelay: 1_000,
growthRate: 2,
jitter: 0.1,
...options,
};
}
/** /**
* Create a new ExponentialBackoff instance * Create a new ExponentialBackoff instance
* *
@@ -43,29 +68,31 @@ export class ExponentialBackoff {
return backoff.run(taskFn, onError); return backoff.run(taskFn, onError);
} }
private readonly options: ExponentialBackoffOptions;
/** /**
* Creates a new exponential-backoff instance. * Calculate the delay before we should attempt to retry
* *
* Unspecified options use the defaults listed below. * @param options - The configuration for the exponential backoff
* * @param attempt - The current attempt number
* @param options - Exponential-backoff configuration overrides. * @returns The time in milliseconds before another attempt should be made
* @param options.maxDelay - Maximum delay between retries. Default: `10_000` ms.
* @param options.maxAttempts - Maximum number of attempts; `0` retries indefinitely. Default: `10`.
* @param options.baseDelay - Delay used as the basis for the first retry. Default: `1_000` ms.
* @param options.growthRate - Multiplier applied to the delay after each attempt. Default: `2`.
* @param options.jitter - Maximum proportional reduction subtracted from each delay (01). Default: `0.1`.
*/ */
constructor(options: Partial<ExponentialBackoffOptions> = {}) { public static calculateDelay(options: ExponentialBackoffOptions, attempt: number): number {
this.options = { // Get the power of the growth rate
maxDelay: 10_000, const power = options.growthRate ** attempt;
maxAttempts: 10,
baseDelay: 1_000, // Get the delay before jitter or limit
growthRate: 2, const rawDelay = options.baseDelay * power;
jitter: 0.1,
...options, // Cap the delay to the maximum. Do this before the jitter so jitter does not become larger than delay
}; const cappedDelay = Math.min(rawDelay, options.maxDelay);
// Get a random number for the amount to "jitter" the delay by
const jitterAmount = Math.random();
// Calculate the jitter
const jitter = jitterAmount * options.jitter * cappedDelay;
// Subtract the jitter from the delay
return cappedDelay - jitter;
} }
/** /**
@@ -142,33 +169,6 @@ export class ExponentialBackoff {
// We completed the loop without ever succeeding. Throw an ExponentialBackoffMaxRetriesHitError with all the errors we got // We completed the loop without ever succeeding. Throw an ExponentialBackoffMaxRetriesHitError with all the errors we got
throw new ExponentialBackoffMaxRetriesHitError(errors); throw new ExponentialBackoffMaxRetriesHitError(errors);
} }
/**
* Calculate the delay before we should attempt to retry
*
* @param options - The configuration for the exponential backoff
* @param attempt - The current attempt number
* @returns The time in milliseconds before another attempt should be made
*/
public static calculateDelay(options: ExponentialBackoffOptions, attempt: number): number {
// Get the power of the growth rate
const power = options.growthRate ** attempt;
// Get the delay before jitter or limit
const rawDelay = options.baseDelay * power;
// Cap the delay to the maximum. Do this before the jitter so jitter does not become larger than delay
const cappedDelay = Math.min(rawDelay, options.maxDelay);
// Get a random number for the amount to "jitter" the delay by
const jitterAmount = Math.random();
// Calculate the jitter
const jitter = jitterAmount * options.jitter * cappedDelay;
// Subtract the jitter from the delay
return cappedDelay - jitter;
}
} }
export type ExponentialBackoffOptions = { export type ExponentialBackoffOptions = {