@bernierllc/retry-policy
Version:
Atomic retry policy utilities with exponential backoff and jitter
250 lines (216 loc) • 7.36 kB
JavaScript
#!/usr/bin/env node
/*
Copyright (c) 2025 Bernier LLC
This file is licensed to the client under a limited-use license.
The client may use and modify this code *only within the scope of the project it was delivered for*.
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
*/
/**
* Configuration initialization script for @bernierllc/retry-policy core package
*
* Usage: npm run config:init
*/
const fs = require('fs');
const path = require('path');
// Package configuration
const PACKAGE_NAME = 'retry-policy';
const PACKAGE_TYPE = 'core';
const CONFIG_FILE = `${PACKAGE_NAME}.config.js`;
// Configuration template
const CONFIG_TEMPLATE = `/*
Copyright (c) 2025 Bernier LLC
This file is licensed to the client under a limited-use license.
The client may use and modify this code *only within the scope of the project it was delivered for*.
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
*/
/**
* @bernierllc/retry-policy configuration
*
* This is a behavioral core package that supports optional runtime configuration
* while maintaining full backward compatibility. All settings are optional.
*/
module.exports = {
// =============================================
// RETRY POLICY CONFIGURATION
// =============================================
/**
* Maximum number of retry attempts
* @default 5
* Environment: RETRY_MAX_RETRIES
*/
maxRetries: 3,
/**
* Initial delay in milliseconds before first retry
* @default 1000
* Environment: RETRY_INITIAL_DELAY
*/
initialDelayMs: 1000,
/**
* Maximum delay in milliseconds (prevents infinite backoff)
* @default 30000
* Environment: RETRY_MAX_DELAY
*/
maxDelayMs: 30000,
/**
* Exponential backoff factor
* @default 2
* Environment: RETRY_BACKOFF_FACTOR
*/
backoffFactor: 2.0,
/**
* Enable/disable jitter to prevent thundering herd
* @default true
* Environment: RETRY_JITTER
*/
jitter: true,
/**
* Enable/disable retry functionality globally
* Setting to false will disable all retries
* @default true
* Environment: RETRY_ENABLED
*/
enabled: true,
// =============================================
// BACKOFF STRATEGY CONFIGURATION
// =============================================
/**
* Backoff strategy configuration
*/
backoff: {
/**
* Backoff strategy type
* Values: 'exponential' | 'linear' | 'constant'
* @default 'exponential'
* Environment: RETRY_BACKOFF_TYPE
*/
type: 'exponential',
/**
* Base delay for backoff calculations
* @default 1000
* Environment: RETRY_BACKOFF_BASE_DELAY
*/
baseDelay: 1000,
/**
* Maximum delay cap
* @default 30000
* Environment: RETRY_BACKOFF_MAX_DELAY
*/
maxDelay: 30000,
/**
* Backoff multiplier for exponential strategy
* @default 2
* Environment: RETRY_BACKOFF_MULTIPLIER
*/
factor: 2.0,
/**
* Jitter configuration
*/
jitter: {
/**
* Jitter type
* Values: 'none' | 'full' | 'equal' | 'decorrelated'
* @default 'full'
* Environment: RETRY_JITTER_TYPE
*/
type: 'full',
/**
* Jitter factor (0-1)
* @default 0.1
* Environment: RETRY_JITTER_FACTOR
*/
factor: 0.1
}
}
// =============================================
// NOTES FOR CORE PACKAGE CONFIGURATION
// =============================================
/*
* Core Package Principles:
* - Configuration is OPTIONAL - package works perfectly without it
* - No breaking changes - all existing usage patterns continue to work
* - Constructor parameters take precedence over configuration
* - Service packages can inject global configuration
*
* Service Package Integration:
* Service packages can configure this core package globally:
*
* import { setGlobalRetryPolicyConfig } from '@bernierllc/retry-policy';
*
* setGlobalRetryPolicyConfig({
* maxRetries: 5,
* initialDelayMs: 500,
* backoff: { type: 'exponential', factor: 1.5 }
* });
*
* Configuration Precedence (lowest to highest):
* 1. Package defaults
* 2. Global configuration (from service packages)
* 3. Configuration file (this file)
* 4. Environment variables
* 5. Constructor parameters (highest priority)
*/
};
`;
class ConfigurationInitializer {
constructor() {
this.configPath = path.join(process.cwd(), CONFIG_FILE);
}
initialize() {
console.log(`🔧 Initializing configuration for ${PACKAGE_NAME} (${PACKAGE_TYPE} package)`);
console.log('');
// Check if configuration file already exists
if (fs.existsSync(this.configPath)) {
console.log(`⚠️ Configuration file already exists: ${CONFIG_FILE}`);
console.log(' Use --force to overwrite existing configuration');
const forceOverwrite = process.argv.includes('--force');
if (!forceOverwrite) {
console.log('');
console.log('💡 To view current configuration:');
console.log(` npm run config:print`);
console.log('');
console.log('💡 To validate configuration:');
console.log(` npm run config:validate`);
return;
}
}
try {
// Write configuration file
fs.writeFileSync(this.configPath, CONFIG_TEMPLATE, 'utf8');
console.log(`✅ Created configuration file: ${CONFIG_FILE}`);
console.log('');
console.log('📋 Configuration includes:');
console.log(' • Optional runtime configuration for behavioral core package');
console.log(' • Retry policy settings (attempts, delays, backoff strategies)');
console.log(' • Global enable/disable functionality');
console.log(' • Service package integration support');
console.log(' • Full backward compatibility');
console.log('');
console.log('🔧 Available commands:');
console.log(` npm run config:print - Print resolved configuration`);
console.log(` npm run config:validate - Validate configuration`);
console.log('');
console.log('🌍 Environment variables (optional):');
console.log(' RETRY_MAX_RETRIES - Maximum retry attempts');
console.log(' RETRY_INITIAL_DELAY - Initial delay in ms');
console.log(' RETRY_ENABLED - Enable/disable retries');
console.log(' RETRY_BACKOFF_TYPE - Backoff strategy (exponential/linear/constant)');
console.log('');
console.log('🔗 Service Package Integration:');
console.log(' Service packages can configure this core package using:');
console.log(' setGlobalRetryPolicyConfig({ maxRetries: 5, ... })');
console.log('');
console.log('📖 See README.md for complete documentation and usage examples');
} catch (error) {
console.error('❌ Failed to create configuration file:', error.message);
process.exit(1);
}
}
}
function main() {
const initializer = new ConfigurationInitializer();
initializer.initialize();
}
if (require.main === module) {
main();
}
module.exports = { ConfigurationInitializer };