Skip to content

Instantly share code, notes, and snippets.

@dmmulroy
Created May 14, 2025 15:14
Show Gist options
  • Save dmmulroy/d995f89b73e024f7451657a822e46744 to your computer and use it in GitHub Desktop.
Save dmmulroy/d995f89b73e024f7451657a822e46744 to your computer and use it in GitHub Desktop.
import { Schedule } from 'effect';
import type { Duration, DurationInput } from 'effect/Duration';
/**
* Configuration options for exponential backoff retry strategy
*
* Defines the parameters for configuring a retry mechanism with exponential backoff
*
* @property {DurationInput} delay - Initial delay between retry attempts. Defaults to 100ms.
* @property {number} [growthFactor=2.0] - Factor by which the delay increases exponentially.
* @property {boolean} [jitter=true] - Whether to add randomness to the retry delay to prevent thundering herd problem.
* @property {number} [maxRetries=3] - Maximum number of retry attempts.
*/
export type ExponentialBackoffOptions = Readonly<{
/**
* Initial delay between retry attempts
* @default 100
*/
delay: DurationInput;
/**
* Factor by which the delay increases exponentially
* @default 2.0
*/
growthFactor?: number;
/**
* Whether to add randomness to the retry delay to prevent thundering herd problem
* @default true
*/
jitter?: boolean;
/**
* Maximum number of retry attempts
* @default 3
*/
maxRetries?: number;
}>;
/**
* Default configuration for exponential backoff retry strategy
*
* @internal
* Provides out-of-the-box configuration for retry mechanism
*/
const defaultExponentialBackoffOptions = {
delay: 100,
growthFactor: 2.0,
jitter: true,
maxRetries: 3,
} as const satisfies ExponentialBackoffOptions;
/**
* Creates an exponential backoff retry policy with configurable options
*
* @internal
* @param {ExponentialBackoffOptions} [options] - Optional configuration to override defaults
* @returns {Schedule.Schedule} A retry schedule with exponential backoff and optional jitter
*
* @example
* // Create a custom retry policy with longer delays and more retries
* const customPolicy = makeExponentialBackoffPolicy({
* delay: 500,
* maxRetries: 5,
* jitter: false
* });
*/
const makeExponentialBackoffPolicy = (
options?: ExponentialBackoffOptions,
): Schedule.Schedule<[Duration, number]> => {
const opts = { ...defaultExponentialBackoffOptions, ...options };
const retryPolicy = Schedule.intersect(
Schedule.exponential(opts.delay, opts.growthFactor),
Schedule.recurs(opts.maxRetries),
).pipe((policy) => (opts.jitter ? Schedule.jittered(policy) : policy));
return retryPolicy;
};
/**
* Default exponential backoff retry policy
*
* @internal
* Provides a pre-configured retry policy with standard exponential backoff settings
*/
const defaultExponentialBackoffPolicy = makeExponentialBackoffPolicy(
defaultExponentialBackoffOptions,
);
/**
* Retry utility with exponential backoff policy generation
*
* Provides methods for creating and accessing retry policies.
*
* @property makeExponentialBackoffPolicy - Creates a custom exponential backoff retry policy.
* @property exponentialBackoffPolicy - Default exponential backoff retry policy.
* @property noRetryPolicy - A policy that does not perform any retries.
* @property once - A policy that retries exactly once.
*/
export const RetryPolicy = {
/**
* Creates a custom exponential backoff retry policy
*
* @param {ExponentialBackoffOptions} [options] - Configuration for the retry policy
* @returns {Schedule.Schedule<[Duration, number]>} A customized retry schedule
*/
makeExponentialBackoffPolicy,
/**
* Default exponential backoff retry policy
*/
exponentialBackoffPolicy: defaultExponentialBackoffPolicy,
/**
* Default no retry policy
*/ noRetryPolicy: Schedule.stop,
/**
* Default retry once policy
*/
once: Schedule.once,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment