Skip to content

Instantly share code, notes, and snippets.

@kshepherd
Last active February 22, 2018 00:15
Show Gist options
  • Save kshepherd/317e221a35eb6ad532ad5e453d7c4c9c to your computer and use it in GitHub Desktop.
Save kshepherd/317e221a35eb6ad532ad5e453d7c4c9c to your computer and use it in GitHub Desktop.
Draft Pattern: Safe Delayed Retries
var Promise = require('bluebird');
/*
* Safe Delayed Retries
*
* This test pattern simulates a single delayed retry for an operation
* that might have failed but doesn't always... in my case, a MSSQL 'deadlocked transaction, please run again'
* error response that I want to retry rather than skipping that transaction or failing outright.
*
* I've set it up so that on >=0.5 random roll, the operation passes.
* On a pass, results are handled and app carries on.
*
* On > 0.5 it fails.
* On a failure, result is checked (eg error code) and if under 0.3 we decide this is an op to retry once
* If above 0.3, we could reject or log and carry on, or whatever.
*
* On a second failure, we also do a hard reject or catch-and-log.
*
*/
var aThingThatSometimesFails = function(inputString) {
return new Promise(function(resolve, reject) {
var roll = Math.random();
if(roll >= 0.5) {
// pass!
var success = 'The roll of ' + roll + ' means we passed (>=0.5) for '+inputString+'!';
resolve({data:success,roll:roll});
}
else {
var err = 'We failed (<0.5) for ' + inputString;
reject({message:err,roll:roll});
}
});
};
var handleSuccess = function(result) {
console.log("I'm handling a successful sql result!\n");
console.dir(result);
};
function attemptThingThatWeSometimesRetry() {
var i = 0;
//for (var i = 0; i < 20; i++) {
var attempt=1;
var inputString = "Test #"+i+", attempt "+attempt;
aThingThatSometimesFails(inputString)
.then(function(result) {
handleSuccess(result);
}).catch(function(err) {
console.log(err.message);
if(err.roll < 0.3) {
console.log("This is one of the error responses (roll < 0.3) we try to retry once (eg SQL deadlock)");
return new Promise(function(resolve, reject) {
try {
setTimeout(function(){
attempt++;
var inputString = "Test #"+i+", attempt "+attempt;
return resolve(aThingThatSometimesFails(inputString));
},5000);
} catch(e) {
reject(e);
}
})
}
else {
Promise.reject("This is one of the error responses (roll > 0.3 && < 0.5)" +
" we don't retry, it's a hard reject (auth error) or perhaps a catch-and-log (null result for query)");
}
}).then(function(result){
if(result) {
handleSuccess(result);
}
}).catch(function(err) {
if(attempt==2) {
err.message += '. Second failure, rejecting.';
}
Promise.reject(err.message);
});
//}
}
attemptThingThatWeSometimesRetry();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment