All files / hof resilient.js

100% Statements 12/12
75% Branches 3/4
100% Functions 3/3
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42    1x             2x         2x     3x 3x       5x   1x           4x 4x 4x         3x     2x  
import { VError, MultiError } from 'verror';
 
const DEFAULT_CONFIG = {
	task: 'promise resolution',
	attempts: 3,
	context: null
};
 
export default function resilient(asyncFn, config) {
	config = {
		...DEFAULT_CONFIG,
		...(config || {})
	};
 
	const maxAttempts = config.attempts;
 
	function resilientFn(...args) {
		const errors = [];
		let currentAttempts = 0;
 
		// recursive "catcher"
		function statefulCatch(err) {
			if (currentAttempts >= config.attempts) {
				// give up
				throw new VError({
					name: 'ResilientPromiseFailed',//
					cause: new MultiError(errors),
					info: { task: config.task, maxAttempts }
				}, `Resilient ${config.task} failed after ${maxAttempts}`);
			} else {
				currentAttempts += 1;
				errors.push(err);
				return asyncFn.apply(config.context, args).catch(statefulCatch);
			}
		}
 
		// kick off the chain
		return asyncFn.apply(config.context, args).catch(statefulCatch);
	}
 
	return resilientFn;
}