docs/retry-mechanisms-enhancement.md
This document describes the improvements made to CodeceptJS retry mechanisms to eliminate overlaps and provide better coordination.
CodeceptJS previously had multiple retry mechanisms that could overlap and conflict:
I.retry() callsThese mechanisms could result in:
lib/listener/enhancedGlobalRetry.js)New Features:
Priority System:
const RETRY_PRIORITIES = {
MANUAL_STEP: 100, // I.retry() or step.retry() - highest priority
STEP_PLUGIN: 50, // retryFailedStep plugin
SCENARIO_CONFIG: 30, // Global scenario retry config
FEATURE_CONFIG: 20, // Global feature retry config
HOOK_CONFIG: 10, // Hook retry config - lowest priority
}
lib/plugin/enhancedRetryFailedStep.js)New Features:
Coordination Logic:
deferToScenarioRetries: falselib/retryCoordinator.js)New Features:
Key Functions:
validateConfig() - Detects configuration conflicts and excessive retry countsregisterRetry() - Registers retry mechanisms with priority coordinationgetEffectiveRetryConfig() - Returns the active retry configuration for a targetgenerateRetrySummary() - Provides debugging information about active retry mechanismsThe enhanced retry mechanisms are backward compatible. Existing configurations will continue to work with these improvements:
Old Configuration (potentially conflicting):
module.exports = {
retry: 3, // scenario retries
plugins: {
retryFailedStep: {
enabled: true,
retries: 2, // step retries - could result in 3 * 3 = 9 executions
},
},
}
Recommended Configuration:
module.exports = {
retry: 3, // scenario retries only
plugins: {
retryFailedStep: {
enabled: false, // disable to avoid conflicts
},
},
}
Recommended Configuration:
module.exports = {
plugins: {
retryFailedStep: {
enabled: true,
retries: 2,
ignoredSteps: ['amOnPage', 'wait*'], // customize as needed
},
},
// No global retry configuration
}
module.exports = {
retry: {
Scenario: 2, // scenario retries for most tests
},
plugins: {
retryFailedStep: {
enabled: true,
retries: 1,
deferToScenarioRetries: true, // automatically coordinate (default)
},
},
}
Use the new retry coordinator to validate your configuration:
const retryCoordinator = require('codeceptjs/lib/retryCoordinator')
// Validate your configuration
const warnings = retryCoordinator.validateConfig(yourConfig)
if (warnings.length > 0) {
console.log('Retry configuration warnings:')
warnings.forEach(warning => console.log(' -', warning))
}
The new retry mechanisms provide clearer logging:
[Global Retry] Scenario retries: 3
[Step Retry] Deferred to scenario retries (3 retries)
[Retry Coordinator] Registered scenario retry (priority: 30)
None. All existing configurations continue to work.
plugins: {
retryFailedStep: {
enabled: true,
retries: 2,
deferToScenarioRetries: true, // NEW: automatically coordinate with scenario retries
minTimeout: 1000,
maxTimeout: 10000,
factor: 1.5,
ignoredSteps: ['wait*', 'amOnPage']
}
}
deferToScenarioRetries (boolean, default: true) - When true, step retries are disabled if scenario retries are configuredconst retryCoordinator = require('codeceptjs/lib/retryCoordinator')
const warnings = retryCoordinator.validateConfig(Config.get())
console.log('Configuration warnings:', warnings)
Run tests with --verbose to see detailed retry coordination logs.
// In your test hooks
const summary = retryCoordinator.generateRetrySummary()
console.log('Retry mechanisms active:', summary)