How to suppress error when REST service returns an error

Goal: Prevent the system notification from popping up when a REST resource query fails

Steps: I've tried un-checking "Show notification failure" in the Response tab of the REST query, with no effect. To reproduce it you need an API that returns a status code like 503. Call that service from a REST service query that is manually triggered asynchronously.

Details:
I have an app which needs to call a long-running REST service in the background. Somewhere in the stack, the request times out after 10 seconds. I'm not sure if it is in the ReTool app (running self-hosted on the docker image) or what. But it would definitely timeout after 2 minutes, because it is going through an AWS Application Load Balancer which times out requests that exceed 2 minutes. In any case, this fine, since we don't want the UI to wait for the response and the user doesn't need to know if the call fails. I achieve that by triggering it inside an async script block:

(async () => {
  utils.showNotification({title: "Changes submitted - refresh in a few moments to see changes.", description: "", notificationType: "success", duration: 5});
  result = await SubmitTranslationChanges.trigger({additionalScope: {rowData: tblTranslatedStrings.recordUpdates }});
})().then(() => {
  // log it
});

The problem is; the "400" error returned by the ReTool backend is still displayed in a popup after 10 seconds, which is not ideal from a UX perspective.

Screenshots:

Can you show the query SubmitTranslationChanges's configuration? Have you tried configuring the Error handler on the query?

Well, no, I have not :slight_smile:
image
What should I put in the Failure event handler to suppress the notification?

sorry if I got something wrong, but have you tried returning the promise returned from .trigger() so in the chain continuation you can get the response and the code for logging and processing... i guess since you're already introducing await you could do it in the same block but then it wouldn't fit your comment for where logging should happen:

I've been using a different language in VSCode for a few days now I seem to be getting confused on a few JS things, so sorry for some of the comments or if I'm just no where near whats going on here

(async () => {
  utils.showNotification({title: "Changes submitted - refresh in a few moments to see changes.", description: "", notificationType: "success", duration: 5});
  result = await SubmitTranslationChanges.trigger({additionalScope: {rowData: tblTranslatedStrings.recordUpdates }});
  const resultObj = JSON.parse(result);  //sorry, right now i can't remember if you need this or not lol but if you don't use 'result' in the switch below instead of 'resultObj'
  switch (resultObj.code){
    //add a case for any codes where you need to respond to them
    case 200:
      console.log("Server Response", result);
      break;
    default:
      break;
  }
})().then(() => {
  // log it
});

or

//we don't need async since we aren't using await.  i could be wrong, you might need to use 'return await'.  

utils.showNotification({title: "Changes submitted - refresh in a few moments to see changes.", description: "", notificationType: "success", duration: 5});
return SubmitTranslationChanges.trigger({additionalScope: {rowData: tblTranslatedStrings.recordUpdates }});
}).then((response) => {
// log it
// i don't think you need to call JSON.parse down here even if you do need to above, if I remember right it's some of that js magic
switch (response.code){
  //add a case for any codes where you need to respond to them
  case 200:
    console.log("Server Response", result);
    return;
    //break; //most linters will error on this since it's unreachable.  i'd suggest return over break to stick more in line w the whole 'fail fast' thing or whatever it's called XD, either way break can be ambiguous as to if more processing ends up being done or not.  when debugging you know for sure that you don't need to look below here which can be nice but obviously it's up to you which to use.
  default:
    break;
}

The logging is not actually important.
So what about the above example results in suppressing the (400) notification from the backend? It doesn't seem to do anything particularly different in terms of the result, other than conditionally logging on the the response code value.

What happens if you throw a return; in the error handler, does it supersede the default error message and return nothing?

Found it! You can disable this Show Notification on Failure settings on the SubmitTranslationChanges query and it will not show the popup

it's not actually about the longging. in the code you had provided, the promise results aren't actually being handled. there's no return statement visible but I think it's returning the obj(or promise?) which gets handled on the retool side, giving it the ability to respond to the response code. in the code i posted, when it gets a 200 status code it isn't returning anything, or it shouldn't (you might need to add like null or something i guess?), so the retool side doesn't get that part.

again, maybe I'm wrong I've been using a completely different language most of this week and now I seem to be confusing myself on everything JS related.

EDIT: oh you said 503, not 200... just change the number lol sorry

As I mentioned above, I tried that...did not work.

Using the first approach failed because result is 'undefined'.
Using the second approach doesn't work because it is not async, so it blocks further events in the UI until the error is returned.
This is what I wound up with:

console.log("calling SubmitTranslationChanges");
(async () => {
  utils.showNotification({title: "Changes submitted - refresh in a moment to see changes.", description: "", notificationType: "success", duration: 5});
  let result = await SubmitTranslationChanges.trigger({
    additionalScope: {rowData: tblTranslatedStrings.recordUpdates },
    onSuccess: function (data) {
      console.log("SubmitTranslationChanges Success:" + data);
    },
    onFailure: function (error) {
      console.log("SubmitTranslationChanges Failure:" + error);
      console.log("probably due to gateway timeout");
    },
  });
})().then(() => {
  console.log("SubmitTranslationChanges submitted to "  + SubmitTranslationChanges.query + ", data:" + SubmitTranslationChanges.rawData);
  // for some reason REST requests are timing out after 10 seconds regardless of timeout setting in query...supress for now
  //console.log(result);
  //utils.showNotification({title: "Background Translation processing complete: "+result, description: "", notificationType: "success", duration: 10});
});

Thanks, Andy

1 Like

:smiley: using the onSuccess and onFailure event handlers/callback fn is sleek and quite honestly the best (possibly only) solution, I always forget you can add those when you call .trigger() even after you create the query and save it using the GUI. I'ma have to bookmark your post and hope I remember next time :joy:

i'd perhaps suggest marking your post as the solution for others in the future to find easily (or mark Harry's post? you were looking for code but maybe his suggestion/pic tipped you off, idk... or just mark yours for the contest this month and try to remember to change it to his? lol sorry retool team)

1 Like