- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-29-2023 02:31 PM
Hello,
I have a requirement where the user enters search queries and domains on a UI Page, which then executes outbound API calls for each combination to a very slow-to-respond external source via GlideAjax.
Essentially it's a lot of outbound REST messages that can combine to take 15-30 minutes; and in addition, this feature needs to be table-less at least from the start, meaning that it does not have access to any table to create, read, or update from/to.
I have tried two techniques:
1. Sending all the inputted data to a script include via GlideAjax and executing REST messages within two for loops
// THIS IS PSEUDOCODE REPRESENTING THE SCRIPT INCLUDE CALLED VIA GlideAjax
for (var query in queryArray) {
for (var domain in domainArray) {
var msg = new sn_ws.RESTMessageV2('The API Call', 'Default GET');
msg.setStringParameterNoEscape('query', query);
msg.setStringParameterNoEscape('domain', domain);
var response = msg.execute();
var body = response.getResponseBody();
// Etc. etc.
}
}
This, as you might imagine, would consistently get cancelled by Transaction Quotas on the SNOW instance. Changing this quota to be large enough is not an option (too large). So I tried:
2. Splitting each query and domain combo into it's own separate GlideAjax call, and had the Script Include process one combo at a time instead of all of them at once:
// THIS IS PSEUDOCODE REPRESENTING THE CLIENT SCRIPT FOR THE UI PAGE AND THE CALLBACK
for (var query in queryArray) {
for (var domain in domainArray) {
var ga = new GlideAjax('MyScriptInclude');
ga.addParam('sysparm_name', 'mainFunc');
ga.addParam('sysparm_query', query);
ga.addParam('sysparm_domain', domain);
ga.getXMLAnswer(callbackFunc);
}
}
function callbackFunc(answer) {
var parsedAnswer = JSON.parse(answer);
document.getElementById('outputText').value += parsedAnswer['resultString'];
}
This led to inconsistent behavior at best - it would sometimes process all the calls fine, other times only 70%, other times none whatsoever.
In the average, successful case, each API request takes approx. 45 seconds, and I very strictly log any success or failure of these requests. However, the failures I'm getting for case 2 have no thrown errors, warnings, info messages, or otherwise in either System or Transaction logs.
Looking for any kind of insight into this situation - anything I can try, or if I should just resort to doing this API processing on a platform other than SNOW.
Thanks
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-30-2023 02:31 PM
For those who stumble upon this I have found a solution:
Case 2 was what I was working with because obviously one large batch was always going to take too long. But in case 2 there was still a "batch" of separate GlideAjax calls with each conducting a REST API call.
Although asynchronous, this batch is still queued, and the transaction time for each call starts when it is enqueued - not when processing actually starts (although there is a notion of "stall" time - I couldn't determine where this came from, and it didn't help enough). So calls at the end of the queue were getting cancelled by SNOW when they passed the default 298s UI transaction quota; and the number of calls cancelled by this depended on the latency of the API at the time - causing inconsistent results.
I fixed this by (unfortunately) using getXMLWait() and forcing synchronicity. Although this does muck up the browser page for the duration of processing, it allows each call to have their transaction quota timing start only when they actually begin processing.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-29-2023 03:54 PM
Hello @Patrick55,
If you are just making an API call, why are you using GlideAjax?
In other words, call the API directly from the client side(browser), why are you first going to ServiceNow and then going to the API end point.
I don't see that you are dependent on any ServiceNow data for the API call.
I would suggest using XMLHttpRequest method instead to perform your API call.
// Create a new XMLHttpRequest object
var xhr = new XMLHttpRequest();
// Define the HTTP method, the REST endpoint URL, and whether the request is asynchronous or not
xhr.open("GET", "https://jsonplaceholder.typicode.com/todos/1", true);
// Define what to do when the request is successful
xhr.onload = function() {
// Check if the status code is 200 (OK)
if (xhr.status === 200) {
// Parse the response data as JSON
var data = JSON.parse(xhr.responseText);
// Log the data to the console
console.log(data);
}
};
// Define what to do when the request fails
xhr.onerror = function() {
// Log the error to the console
console.error("An error occurred");
};
// Send the request
xhr.send();
Hope this helps.
Kind Regards,
Swarnadeep Nandy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-30-2023 08:32 AM - edited 08-30-2023 08:33 AM
Hey @SwarnadeepNandy - thank you for your reply! I hadn't thought of making requests directly from the client.
I tried it, and unfortunately due to the configuration of the endpoint I'm requesting from, I am unable to make this kind of CORS request; and if I were to be able to I'm still concerned with the amount of requests and the time they take causing a completely unresponsive page (as opposed to the mildly unresponsive one that is acceptable haha), or the strange behavior I noted in case 2.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-30-2023 02:31 PM
For those who stumble upon this I have found a solution:
Case 2 was what I was working with because obviously one large batch was always going to take too long. But in case 2 there was still a "batch" of separate GlideAjax calls with each conducting a REST API call.
Although asynchronous, this batch is still queued, and the transaction time for each call starts when it is enqueued - not when processing actually starts (although there is a notion of "stall" time - I couldn't determine where this came from, and it didn't help enough). So calls at the end of the queue were getting cancelled by SNOW when they passed the default 298s UI transaction quota; and the number of calls cancelled by this depended on the latency of the API at the time - causing inconsistent results.
I fixed this by (unfortunately) using getXMLWait() and forcing synchronicity. Although this does muck up the browser page for the duration of processing, it allows each call to have their transaction quota timing start only when they actually begin processing.