My app uses an API service called Nylas to send emails. If the Nylas API returns a 429 or 5XX status code they suggest implementing an exponential backoff retry loop. I liked that the OnAfterResponse API Callback can easily read the status code, but when I send it into the retry loop I need to have all the variables created/used in the original service action. How do I do this if I can't call OnAfterResponse inside the service action and the scope of the API method doesn't include its status code?
Hi,
Just a thought, Have you tried to use the exception?
OnAfterResponse: If the status code returns a 429 or 5XX, you throw an exception.
Your Service Action: Create an Exception Handler for Exception that is raised in the OnAfterResponse.
When the API has an error ( Nylas API returns a 429 or 5XX status code ), an Exception will be raised, and the Exception Handler will trigger and call it again and so on if the API still returns an error. The downside is that it may create an infinite retry loop. To prevent this, I think you should create a local variable to count the number of retries, Every time the Handler triggers, increase that variable, and if it reaches the maximum number of retries then stop.Let me know if it works.Cheers,Nam
Thanks @Nam Nguyen ! I'm trying to implement this now and testing it with a simple Pipedream trigger that responds every time with a 429 status code. I've got the debugger open and the exception handler only runs once.
Why would this be happening?
I exposed an API in the module and that API just kicks off the call to Pipedream, and I'm hitting the exposed API from Postman. I'm getting a 500 Internal Server Error code in Postman after the second time the exception gets raised.
Hi @Daniel Johnson ,
Exception handlers in an action, only catch exceptions coming out of the main flow of that same action. So any exception raised in the code that is inside that exception handler branch will not be caught by itself, but by exception handler higher up, if any.
So you'll have to have a mechanism to start over the left main flow again, not re-execute logic in your exception flow.
Not following exactly what you are trying to accomplish, but you could wrap the thing in another action, make this action pass out some sort of result information, and in that wrapper action, decide to execute this one again or not, dependant on that information. Surely, you'll also need to have logic there, to slow down or even stop trying at some point, that can go in that wrapper action.
Dorine
aah, ok,
from what you are saying, do I understand correctly that you expose your own Outsystems API to some outsystems consumers, and inside the logic of that API, you are calling some outside api service.
So in that case, isolate the call to that external consumed api, together with the error handlers into an extra lower level action, that you call in the logic of your own exposed api. Have that lower isolated action return a code indicating if it was successfull.
After calling it, you can have your own api logic make all the decisions about how to deal with this, one of them being to give it another try by calling that isolated new action again.
Thanks for the help @Dorine Boudry ! I marked @Nam Nguyen's original response as the solution because I used his method most of the way, including the loop counter. I did use your method at the end as well and it's working now. I wish there was a way to give credit to you both!
there is ;-)
you are not limited to 1 post marked as solution.
And there's always the option to give a thumbs up, even if something is not the solution.
Hi Daniel Johnson,
In my first comment, my purpose is to illustrate the main idea only. I haven't tested it yet, my apologies :)
As Dorine Boudry pointed out, exception handlers in an action are only capable of catching exceptions that arise from the main flow of the same action. Any exception that is raised within the code that is part of the exception handler branch will not be caught by the handler itself.
There will be a few differences in the way the implementation is carried out.
Firstly, you need to wrap it into a Server Action. When an exception is raised, HasSuccess is set to False. The default value is True.
Here is your Service Action. The LogMessage action is meant for testing purposes, if you want to, you can remove it.
Site Property "Maximum" Variable allows for easy config across environments. Or you can hard code it :) Cheers,Nam
Here's what I've got so far that's working:
When the server action gets called for the first time the LoopIndex is set to 0, and then the Handler just adds one to that (and calculates the pause) and eventually calls that same server action again until the status code is successful or the LoopIndex reaches 9. What do you think?
There are numerous ways to implement an idea once you understand it.
If it functions as anticipated, I'm glad for you :)
Cheers,
Nam
Hey @Daniel Johnson
The solution proposed by the @Nam Nguyen fits considerably well for the use case but as he mentioned regarding the Infinite loop I would suggest you to wake a timer as it by default retries it 3 time automatically and hence we don't need to create separate variables. The biggest advantage is it will be configurable during runtime.
So for eg: It some API service is down, obviously it doesn't makes sense to retry it again and again via timers you could set the retry to number required or even disable it at runtime. Which will not be possible via simple local variable.Else everything look good.