Created
February 23, 2018 11:59
-
-
Save bennadel/2b3a718373a6168a8000a3f762077b09 to your computer and use it in GitHub Desktop.
Creating A Poor Man's Exponential Backoff And Retry Algorithm In Legacy Code Using ColdFusion
This file contains hidden or 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
<cfscript> | |
doTheThing( 4 ); | |
// ------------------------------------------------------------------------------- // | |
// ------------------------------------------------------------------------------- // | |
/** | |
* I do the thing that requires a brittle network connection. I will retry failed | |
* connections using a reasonable backoff; and, eventually throw an error if none | |
* of the retries are successful. | |
* | |
* @id I am the data thing. | |
* @output false | |
*/ | |
public void function doTheThing( required numeric id ) { | |
// Rather than relying on the maths to do backoff calculations, this collection | |
// provides an explicit set of backoff values (in milliseconds). This collection | |
// also doubles as the number of attempts that we should execute against the | |
// remote API. | |
// -- | |
// NOTE: Some randomness will be applied to these values as execution time. | |
var backoffDurations = [ | |
1000, | |
2000, | |
4000, | |
8000, | |
16000, | |
32000, | |
64000, | |
0 // Indicates that the last timeout should be recorded as an error. | |
]; | |
for ( var backoffDuration in backoffDurations ) { | |
try { | |
makeApiRequest( id ); | |
// If we made it this far, the API request didn't throw an error, which | |
// means that it was successful; return out of the method and retry-loop. | |
return; | |
} catch ( any error ) { | |
// If the error is a retriable error AND we still have a non-zero backoff | |
// to consume, sleep the thread and try the request again. | |
if ( isRetrialbeError( error ) && backoffDuration ) { | |
sleep( applyJitter( backoffDuration ) ); | |
// Otherwise, we can't recover from this error, so let it bubble up. | |
} else { | |
rethrow; | |
} | |
} | |
} | |
} | |
/** | |
* I apply a 20% jitter to a given backoff value in order to ensure some kind of | |
* randomness to the collection of requests that may stampede towards an API. | |
* | |
* @value I am the backoff time being nudged. | |
* @output false | |
*/ | |
public numeric function applyJitter( required numeric value ) { | |
// Create a jitter of +/- 20%. | |
var jitter = ( randRange( 80, 120 ) / 100 ); | |
return( fix( value * jitter ) ); | |
} | |
</cfscript> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment