UNPKG

bluebird-retry

Version:

utility for retrying a bluebird promise until it succeeds

145 lines (122 loc) 13.2 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.bluebirdRetry = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var Promise = require('bluebird'); // Subclass of Error that can be thrown to indicate that retry should stop. // // If called with an instance of Error subclass, then the retry promise will be // rejected with the given error. // // Otherwise the cancel error object itself is propagated to the caller. // function StopError(err) { this.name = 'StopError'; if (err instanceof Error) { this.err = err } else { this.message = err || 'cancelled' } } StopError.prototype = Object.create(Error.prototype); retry.StopError = StopError; // Retry `func` until it succeeds. // // For each attempt, invokes `func` with `options.args` as arguments and // `options.context` as `this`. // // Waits `options.interval` milliseconds (default 1000) between attempts. // // Increases wait by a factor of `options.backoff` each interval, up to // a limit of `options.max_interval`. // // Keeps trying until `options.timeout` milliseconds have elapsed, // or `options.max_tries` have been attempted, whichever comes first. // // If neither is specified, then the default is to make 5 attempts. // function retry(func, options) { options = options || {}; var interval = typeof options.interval === 'number' ? options.interval : 1000; var max_tries, giveup_time; if (typeof(options.max_tries) !== 'undefined') { max_tries = options.max_tries; } if (options.timeout) { giveup_time = new Date().getTime() + options.timeout; } if (!max_tries && !giveup_time) { max_tries = 5; } var tries = 0; var start = new Date().getTime(); // If the user didn't supply a predicate function then add one that // always succeeds. // // This is used in bluebird's filtered catch to flag the error types // that should retry. var predicate = options.predicate || function(err) { return true; } var stopped = false; function try_once() { var tryStart = new Date().getTime(); return Promise.attempt(function() { return func.apply(options.context, options.args); }) .caught(StopError, function(err) { stopped = true; if (err.err instanceof Error) { return Promise.reject(err.err); } else { return Promise.reject(err); } }) .caught(predicate, function(err) { if (stopped) { return Promise.reject(err); } ++tries; if (tries > 1) { interval = backoff(interval, options); } var now = new Date().getTime(); if ((max_tries && (tries === max_tries) || (giveup_time && (now + interval >= giveup_time)))) { if (! (err instanceof Error)) { var failure = err; if (failure) { if (typeof failure !== 'string') { failure = JSON.stringify(failure); } } err = new Error('rejected with non-error: ' + failure); err.failure = failure; } else if (options.throw_original) { return Promise.reject(err); } var timeout = new Error('operation timed out after ' + (now - start) + ' ms, ' + tries + ' tries with error: ' + err.message); timeout.failure = err; timeout.code = 'ETIMEDOUT'; return Promise.reject(timeout); } else { var delay = interval - (now - tryStart); if (delay <= 0) { return try_once(); } else { return Promise.delay(delay).then(try_once); } } }); } return try_once(); } // Return the updated interval after applying the various backoff options function backoff(interval, options) { if (options.backoff) { interval = interval * options.backoff; } if (options.max_interval) { interval = Math.min(interval, options.max_interval); } return interval; } module.exports = retry; },{"bluebird":undefined}]},{},[1])(1) }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJsaWIvYmx1ZWJpcmQtcmV0cnkuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsInZhciBQcm9taXNlID0gcmVxdWlyZSgnYmx1ZWJpcmQnKTtcblxuLy8gU3ViY2xhc3Mgb2YgRXJyb3IgdGhhdCBjYW4gYmUgdGhyb3duIHRvIGluZGljYXRlIHRoYXQgcmV0cnkgc2hvdWxkIHN0b3AuXG4vL1xuLy8gSWYgY2FsbGVkIHdpdGggYW4gaW5zdGFuY2Ugb2YgRXJyb3Igc3ViY2xhc3MsIHRoZW4gdGhlIHJldHJ5IHByb21pc2Ugd2lsbCBiZVxuLy8gcmVqZWN0ZWQgd2l0aCB0aGUgZ2l2ZW4gZXJyb3IuXG4vL1xuLy8gT3RoZXJ3aXNlIHRoZSBjYW5jZWwgZXJyb3Igb2JqZWN0IGl0c2VsZiBpcyBwcm9wYWdhdGVkIHRvIHRoZSBjYWxsZXIuXG4vL1xuZnVuY3Rpb24gU3RvcEVycm9yKGVycikge1xuICAgIHRoaXMubmFtZSA9ICdTdG9wRXJyb3InO1xuICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aGlzLmVyciA9IGVyclxuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubWVzc2FnZSA9IGVyciB8fCAnY2FuY2VsbGVkJ1xuICAgIH1cbn1cblN0b3BFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSk7XG5cbnJldHJ5LlN0b3BFcnJvciA9IFN0b3BFcnJvcjtcblxuXG4vLyBSZXRyeSBgZnVuY2AgdW50aWwgaXQgc3VjY2VlZHMuXG4vL1xuLy8gRm9yIGVhY2ggYXR0ZW1wdCwgaW52b2tlcyBgZnVuY2Agd2l0aCBgb3B0aW9ucy5hcmdzYCBhcyBhcmd1bWVudHMgYW5kXG4vLyBgb3B0aW9ucy5jb250ZXh0YCBhcyBgdGhpc2AuXG4vL1xuLy8gV2FpdHMgYG9wdGlvbnMuaW50ZXJ2YWxgIG1pbGxpc2Vjb25kcyAoZGVmYXVsdCAxMDAwKSBiZXR3ZWVuIGF0dGVtcHRzLlxuLy9cbi8vIEluY3JlYXNlcyB3YWl0IGJ5IGEgZmFjdG9yIG9mIGBvcHRpb25zLmJhY2tvZmZgIGVhY2ggaW50ZXJ2YWwsIHVwIHRvXG4vLyBhIGxpbWl0IG9mIGBvcHRpb25zLm1heF9pbnRlcnZhbGAuXG4vL1xuLy8gS2VlcHMgdHJ5aW5nIHVudGlsIGBvcHRpb25zLnRpbWVvdXRgIG1pbGxpc2Vjb25kcyBoYXZlIGVsYXBzZWQsXG4vLyBvciBgb3B0aW9ucy5tYXhfdHJpZXNgIGhhdmUgYmVlbiBhdHRlbXB0ZWQsIHdoaWNoZXZlciBjb21lcyBmaXJzdC5cbi8vXG4vLyBJZiBuZWl0aGVyIGlzIHNwZWNpZmllZCwgdGhlbiB0aGUgZGVmYXVsdCBpcyB0byBtYWtlIDUgYXR0ZW1wdHMuXG4vL1xuXG5mdW5jdGlvbiByZXRyeShmdW5jLCBvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgICB2YXIgaW50ZXJ2YWwgPSB0eXBlb2Ygb3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicgPyBvcHRpb25zLmludGVydmFsIDogMTAwMDtcblxuICAgIHZhciBtYXhfdHJpZXMsIGdpdmV1cF90aW1lO1xuICAgIGlmICh0eXBlb2Yob3B0aW9ucy5tYXhfdHJpZXMpICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBtYXhfdHJpZXMgPSBvcHRpb25zLm1heF90cmllcztcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy50aW1lb3V0KSB7XG4gICAgICAgIGdpdmV1cF90aW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCkgKyBvcHRpb25zLnRpbWVvdXQ7XG4gICAgfVxuXG4gICAgaWYgKCFtYXhfdHJpZXMgJiYgIWdpdmV1cF90aW1lKSB7XG4gICAgICAgIG1heF90cmllcyA9IDU7XG4gICAgfVxuXG4gICAgdmFyIHRyaWVzID0gMDtcbiAgICB2YXIgc3RhcnQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgIC8vIElmIHRoZSB1c2VyIGRpZG4ndCBzdXBwbHkgYSBwcmVkaWNhdGUgZnVuY3Rpb24gdGhlbiBhZGQgb25lIHRoYXRcbiAgICAvLyBhbHdheXMgc3VjY2VlZHMuXG4gICAgLy9cbiAgICAvLyBUaGlzIGlzIHVzZWQgaW4gYmx1ZWJpcmQncyBmaWx0ZXJlZCBjYXRjaCB0byBmbGFnIHRoZSBlcnJvciB0eXBlc1xuICAgIC8vIHRoYXQgc2hvdWxkIHJldHJ5LlxuICAgIHZhciBwcmVkaWNhdGUgPSBvcHRpb25zLnByZWRpY2F0ZSB8fCBmdW5jdGlvbihlcnIpIHsgcmV0dXJuIHRydWU7IH1cbiAgICB2YXIgc3RvcHBlZCA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gdHJ5X29uY2UoKSB7XG4gICAgICAgIHZhciB0cnlTdGFydCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hdHRlbXB0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KG9wdGlvbnMuY29udGV4dCwgb3B0aW9ucy5hcmdzKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F1Z2h0KFN0b3BFcnJvciwgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICAgICAgc3RvcHBlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKGVyci5lcnIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyLmVycik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXVnaHQocHJlZGljYXRlLCBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RvcHBlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKyt0cmllcztcbiAgICAgICAgICAgICAgICBpZiAodHJpZXMgPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGludGVydmFsID0gYmFja29mZihpbnRlcnZhbCwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgICAgICAgICAgICAgIGlmICgobWF4X3RyaWVzICYmICh0cmllcyA9PT0gbWF4X3RyaWVzKSB8fFxuICAgICAgICAgICAgICAgICAgICAoZ2l2ZXVwX3RpbWUgJiYgKG5vdyArIGludGVydmFsID49IGdpdmV1cF90aW1lKSkpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEgKGVyciBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZhaWx1cmUgPSBlcnI7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmYWlsdXJlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZmFpbHVyZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsdXJlID0gSlNPTi5zdHJpbmdpZnkoZmFpbHVyZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyID0gbmV3IEVycm9yKCdyZWplY3RlZCB3aXRoIG5vbi1lcnJvcjogJyArIGZhaWx1cmUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyLmZhaWx1cmUgPSBmYWlsdXJlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMudGhyb3dfb3JpZ2luYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB0aW1lb3V0ID0gbmV3IEVycm9yKCdvcGVyYXRpb24gdGltZWQgb3V0IGFmdGVyICcgKyAobm93IC0gc3RhcnQpICsgJyBtcywgJyArIHRyaWVzICsgJyB0cmllcyB3aXRoIGVycm9yOiAnICsgZXJyLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICB0aW1lb3V0LmZhaWx1cmUgPSBlcnI7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVvdXQuY29kZSA9ICdFVElNRURPVVQnO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QodGltZW91dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRlbGF5ID0gaW50ZXJ2YWwgLSAobm93IC0gdHJ5U3RhcnQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGVsYXkgPD0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRyeV9vbmNlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5kZWxheShkZWxheSkudGhlbih0cnlfb25jZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRyeV9vbmNlKCk7XG59XG5cbi8vIFJldHVybiB0aGUgdXBkYXRlZCBpbnRlcnZhbCBhZnRlciBhcHBseWluZyB0aGUgdmFyaW91cyBiYWNrb2ZmIG9wdGlvbnNcbmZ1bmN0aW9uIGJhY2tvZmYoaW50ZXJ2YWwsIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucy5iYWNrb2ZmKSB7XG4gICAgICAgIGludGVydmFsID0gaW50ZXJ2YWwgKiBvcHRpb25zLmJhY2tvZmY7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMubWF4X2ludGVydmFsKSB7XG4gICAgICAgIGludGVydmFsID0gTWF0aC5taW4oaW50ZXJ2YWwsIG9wdGlvbnMubWF4X2ludGVydmFsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaW50ZXJ2YWw7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcmV0cnk7XG4iXX0=