@bernierllc/retry-policy
v0.3.0
Published
Atomic retry policy utilities with exponential backoff and jitter
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 }
};Integration Status
Logger Integration
Status: Not applicable
Justification: This is a pure utility package with no runtime state, side effects, or error conditions that require logging. The RetryPolicy class is stateless and deterministic - it simply calculates retry delays and backoff strategies based on attempt numbers and error types. All errors are returned as structured results that calling code can handle, and there are no background operations, network calls, or state changes that would benefit from structured logging.
Pattern: Pure functional utility - no logger integration needed. Logging is handled by consuming packages that use this retry policy.
NeverHub Integration
Status: Not applicable
Justification: This is a core utility package that provides retry policy calculations. It does not participate in service discovery, event publishing, or service mesh operations. Retry policy calculations are stateless utility operations that don't require service registration or discovery. Service-level packages that use this utility can integrate with NeverHub if needed.
Pattern: Core utility - no service mesh integration needed. Service-level packages that use this retry policy can integrate with NeverHub if needed.
Docs-Suite Integration
Status: Ready
Format: TypeDoc-compatible JSDoc comments are included throughout the source code. All public APIs are documented with examples and type information.
Security
This package has zero runtime dependencies and uses only pure TypeScript functions. Security considerations:
- No External Dependencies: All retry logic is implemented internally with no external packages at runtime
- Type Safety: Strict TypeScript typing prevents common runtime errors
- No Network Calls: Pure computational functions with no I/O operations
- No Secret Storage: Does not handle or store any sensitive data
- Audit Clean:
npm auditshows no vulnerabilities (zero dependencies)
For security concerns, please open an issue in the repository.
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
