Package Exports
- @bernierllc/retry-policy
- @bernierllc/retry-policy/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@bernierllc/retry-policy) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@bernierllc/retry-policy
Atomic retry policy utilities with exponential backoff and jitter support.
Overview
@bernierllc/retry-policy provides atomic utilities for implementing retry logic with configurable backoff strategies and jitter. This package is designed to be a core building block that can be used by higher-level retry managers and services.
Features
- Multiple backoff strategies: Exponential, linear, and constant backoff
- Configurable jitter: Full, equal, decorrelated, and no jitter options
- Custom retry conditions: Flexible error evaluation logic
- Type-safe API: Full TypeScript support with strict typing
- Zero dependencies: Pure functions with no external dependencies
- Comprehensive testing: 95%+ test coverage
Installation
npm install @bernierllc/retry-policyQuick Start
import { RetryPolicy, createRetryPolicy } from '@bernierllc/retry-policy';
// Create a retry policy with default settings
const policy = new RetryPolicy();
// Evaluate if an operation should be retried
const result = policy.evaluateRetry(1, new Error('Network error'));
console.log(result);
// {
// shouldRetry: true,
// delay: 2000,
// attempt: 1,
// isFinalAttempt: false
// }API Reference
RetryPolicy Class
The main class for managing retry policies.
Constructor
new RetryPolicy(options?: Partial<RetryPolicyOptions>, backoffConfig?: Partial<BackoffConfig>)Methods
evaluateRetry(attempt: number, error: any): RetryPolicyResultcalculateDelay(attempt: number): numbergetOptions(): Required<RetryPolicyOptions>getBackoffConfig(): BackoffConfigupdateOptions(options: Partial<RetryPolicyOptions>): voidupdateBackoffConfig(config: Partial<BackoffConfig>): void
Utility Functions
createRetryPolicy(options?, backoffConfig?): RetryPolicycalculateRetryDelay(attempt, options?, backoffConfig?): numbershouldRetry(attempt, error, options?): boolean
Usage Examples
Basic Usage
import { RetryPolicy } from '@bernierllc/retry-policy';
const policy = new RetryPolicy({
maxRetries: 3,
initialDelayMs: 1000,
shouldRetry: (error) => error.code === 'NETWORK_ERROR'
});
// In your retry loop
for (let attempt = 0; attempt <= 3; attempt++) {
try {
const result = await someOperation();
break; // Success, exit retry loop
} catch (error) {
const retryResult = policy.evaluateRetry(attempt, error);
if (!retryResult.shouldRetry) {
throw error; // Don't retry, re-throw error
}
// Wait before next attempt
await new Promise(resolve => setTimeout(resolve, retryResult.delay));
}
}Custom Backoff Strategy
import { RetryPolicy } from '@bernierllc/retry-policy';
const policy = new RetryPolicy(
{ maxRetries: 5 },
{
type: 'exponential',
baseDelay: 500,
factor: 3,
maxDelay: 10000,
jitter: {
type: 'full',
factor: 0.1
}
}
);
// This will use exponential backoff with full jitter
const delay = policy.calculateDelay(2); // ~4500ms with jitterDifferent Backoff Types
import { RetryPolicy } from '@bernierllc/retry-policy';
// Exponential backoff (default)
const exponential = new RetryPolicy(undefined, {
type: 'exponential',
baseDelay: 1000,
factor: 2
});
// Delays: 1000ms, 2000ms, 4000ms, 8000ms...
// Linear backoff
const linear = new RetryPolicy(undefined, {
type: 'linear',
baseDelay: 1000
});
// Delays: 1000ms, 2000ms, 3000ms, 4000ms...
// Constant backoff
const constant = new RetryPolicy(undefined, {
type: 'constant',
baseDelay: 1000
});
// Delays: 1000ms, 1000ms, 1000ms, 1000ms...Jitter Types
import { RetryPolicy } from '@bernierllc/retry-policy';
// Full jitter: random value between 0 and delay
const fullJitter = new RetryPolicy(undefined, {
jitter: { type: 'full', factor: 0.1 }
});
// Equal jitter: random value between delay/2 and delay
const equalJitter = new RetryPolicy(undefined, {
jitter: { type: 'equal', factor: 0.1 }
});
// Decorrelated jitter: random value between delay and delay * 3
const decorrelatedJitter = new RetryPolicy(undefined, {
jitter: { type: 'decorrelated', factor: 0.1 }
});
// No jitter: exact delay values
const noJitter = new RetryPolicy(undefined, {
jitter: { type: 'none' }
});Custom Retry Conditions
import { RetryPolicy } from '@bernierllc/retry-policy';
const policy = new RetryPolicy({
maxRetries: 5,
shouldRetry: (error) => {
// Only retry on network errors or 5xx server errors
if (error.code === 'NETWORK_ERROR') return true;
if (error.status >= 500 && error.status < 600) return true;
return false;
},
onRetry: (attempt, delay, error) => {
console.log(`Retry attempt ${attempt} after ${delay}ms due to:`, error.message);
},
onFailure: (error) => {
console.log('All retry attempts exhausted:', error.message);
}
});Configuration
RetryPolicyOptions
interface RetryPolicyOptions {
maxRetries: number; // Maximum number of retry attempts
initialDelayMs: number; // Initial delay in milliseconds
maxDelayMs?: number; // Maximum delay in milliseconds
backoffFactor?: number; // Exponential backoff factor
jitter?: boolean; // Whether to apply jitter
shouldRetry?: (error: any) => boolean; // Custom retry condition
onRetry?: (attempt: number, delay: number, error: any) => void; // Retry callback
onFailure?: (error: any) => void; // Failure callback
}BackoffConfig
interface BackoffConfig {
type: 'exponential' | 'linear' | 'constant'; // Backoff strategy
baseDelay: number; // Base delay in milliseconds
maxDelay: number; // Maximum delay in milliseconds
factor?: number; // Backoff factor for exponential
jitter?: JitterConfig; // Jitter configuration
}JitterConfig
interface JitterConfig {
type: 'none' | 'full' | 'equal' | 'decorrelated'; // Jitter type
factor?: number; // Jitter factor (0-1)
}Default Values
const DEFAULT_RETRY_OPTIONS = {
maxRetries: 5,
initialDelayMs: 1000,
maxDelayMs: 30000,
backoffFactor: 2,
jitter: true,
shouldRetry: () => true,
onRetry: () => {},
onFailure: () => {}
};
const DEFAULT_BACKOFF_CONFIG = {
type: 'exponential',
baseDelay: 1000,
maxDelay: 30000,
factor: 2,
jitter: { type: 'full', factor: 0.1 }
};Testing
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watchContributing
This package follows the Bernier LLC development standards:
- TypeScript strict mode - All code must pass strict type checking
- Comprehensive testing - 95%+ test coverage required
- Documentation - All public APIs must be documented
- Code style - Follow project ESLint configuration
License
ISC License - see LICENSE file for details.
Related Packages
@bernierllc/retry-state- Retry state management and persistence@bernierllc/retry-metrics- Retry performance metrics collection@bernierllc/retry-manager- High-level retry orchestration service