Last active
February 22, 2018 00:15
-
-
Save kshepherd/317e221a35eb6ad532ad5e453d7c4c9c to your computer and use it in GitHub Desktop.
Draft Pattern: Safe Delayed Retries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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