JSPM

@bernierllc/retry-policy

0.1.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 329
  • Score
    100M100P100Q99463F
  • License ISC

Atomic retry policy utilities with exponential backoff and jitter

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-policy

Quick 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): RetryPolicyResult
  • calculateDelay(attempt: number): number
  • getOptions(): Required<RetryPolicyOptions>
  • getBackoffConfig(): BackoffConfig
  • updateOptions(options: Partial<RetryPolicyOptions>): void
  • updateBackoffConfig(config: Partial<BackoffConfig>): void

Utility Functions

  • createRetryPolicy(options?, backoffConfig?): RetryPolicy
  • calculateRetryDelay(attempt, options?, backoffConfig?): number
  • shouldRetry(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 jitter

Different 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:watch

Contributing

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.

  • @bernierllc/retry-state - Retry state management and persistence
  • @bernierllc/retry-metrics - Retry performance metrics collection
  • @bernierllc/retry-manager - High-level retry orchestration service