Add Retry Logic to a Flow Designer Script

Many Flow Designer scripts are implemented without retry logic. This can cause the script to fail if there is a problem such as a failed HTTPS request. Such failures can result in notifications not being sent.

Retry logic allows the operation to be re-executed if it fails, reducing the risk of total script failure.

Prerequisite

Because it depends on a Java class, the retry code can only be executed on an xMatters Agent. Don't let this deter you, though! If you already use an xMatters Agent in your integration, then a simple script change is all that's required. If your integration currently runs on the cloud, you can easily configure it to run on an xMatters Agent instead.

For more information on the xMatters Agent, see the online help.

Example Code

First, we'll show an example of the code without the retry logic, then we'll provide an example with the retry logic so you can see the difference.

Code without the retry logic

Here's a simple example script that depends on a predefined endpoint with the name "test" and a URL similar to "https://example.com". The script is designed to throw an exception if the request to the "test" endpoint doesn't succeed. As a result, the script will fail, and notifications may not be sent.


var endpoint = "test";
var path = "/test";
var payload = "";

var testRequest = http.request({
	endpoint: endpoint,
	method: 'POST',
	path: path,
	headers: {
		'Content-type': 'application/json'
	}
});

// Submit the request
console.log( "About to send request with endpoint: " + endpoint + "; path: " + path + "; and payload: " + payload );
var testResponse = testRequest.write(payload);

// Handle the response
if ( testResponse.statusCode >= 200 && testResponse.statusCode <= 299 ) {
	return testResponse;
} else {
	console.log( "Request failed with response: " + JSON.stringify( testResponse ) );
	throw testResponse;
}

Example code WITH retry logic

Assuming the problem is temporary, it makes sense to wait for a moment and then resend the request. The following code shows how to make this happen:


var endpoint = "test";
var path = "";
var payload = "";

// required by retry logic
var numOfRetries = 2; // so three attempts in total
var retryIntervalMs = 1000; // number of milliseconds to wait before retrying
var thread = Java.type("java.lang.Thread"); // allows execution of the script to be halted for a specified number of milliseconds.

var testRequest = http.request({
	endpoint: endpoint,
	method: 'POST',
	path: path,
	headers: {
		'Content-type': 'application/json'
	}
});

// allow the request to be retried up to two times (by default)
for ( var i=0; i <= numOfRetries; i++ ) {
	console.log( "About to send request with endpoint: " + endpoint + "; path: " + path + "; and payload: " + payload );
	var testResponse = testRequest.write(payload);

	// Handle the response
	if ( testResponse.statusCode >= 200 && testResponse.statusCode <= 299 ) {
		return testResponse;
	} else {
		console.log( "The request failed with response: " + JSON.stringify(testResponse) );
 
		if ( i < numOfRetries ) { 
		// wait for a moment before retrying the request
			console.log( "Sleeping for " + retryIntervalMs + " milliseconds...");
			thread.sleep( retryIntervalMs );
		} else { 
			console.log( "\nNo valid responses were received after " + ( numOfRetries + 1) + " attempts. Exiting..." ); 
			throw testResponse;
		} // end if numOfRetries
	} // end if testResponse
} // end for

The two major changes in the above code are:

  • A for loop causes the request to be submitted up to three times (in other words, the initial request, plus up to two retries).
  • A sleep instruction causes the code to wait for the network problem to go away between requests.

The sleep instruction depends on the Java Thread class, which allows the script to be put on hold for a defined period of time.

The retry code can easily be added to existing scripts. If your use case needs a longer sleep period or more retries, adjust the retryIntervalMs and numOfRetries variables.

Was this article helpful?
0 out of 0 found this helpful

Comments

1 comment

Please sign in to leave a comment.

  • Here's my favorite version.  It adds the ability to increase the wait times for each retry.  This gives more time for whatever is causing the issue to resolve itself.  Note that this isn't checking the returned status of the request.  You could modify this to include that check.  Just make sure that the status isn't one you'd expect will always be returned for the same request.

    const numOfRetries = 4; // So four attempts in total.
    const retryIntervalMs = 500; // Number of milliseconds to wait before retrying. This gets increased by the retryMultiplier on each re-try.
    const retryMultiplier = 2; // Multiply retryIntervalMs by this to increase the interval on each retry.

    const requestReturn = tryRequest(request, payload, numOfRetries, retryIntervalMs, retryMultiplier);

    function tryRequest(request, payload, numOfRetries, retryIntervalMs, retryMultiplier) {
        try {
            return request.write(payload);
        } catch (error) {
            console.log("//ERROR = " + error);
            console.log("// numOfRetries= " + numOfRetries);
            console.log("// retryIntervalMs = " + retryIntervalMs);
            if (numOfRetries > 0) {
                thread.sleep( retryIntervalMs );
                return tryRequest(request, payload, numOfRetries - 1, retryIntervalMs * retryMultiplier, retryMultiplier);
            } else {
                throw new Error(error);
            }
        }
    }

    So in the example above, we try, then wait a second and try again, wait 2 seconds and try again, wait 4 seconds and try a final time for a total of 4 try's over 7 seconds of sleeping.

    (Edited )
    0