How many times in an application dependent on some external resource do you have to write a function or a maybe a whole module to deal with fallback cases? Perhaps the web service you call is down and you fallback to data cached from the last call, or a ftp site is not available so you send the third-party an automatic email to notify them. As developers we are constantly coding fallbacks.
Last week I gave a brief introduction to Polly a fault handling library built for .Net Standard and .Net Core. We looked at the wait and retry functionality that the library has, which would be useful if the external resource is having a blip, but what about if it is down, how do we gracefully degrade?
Our 3rd Party Unsinkable FTP connection
Just like the Titanic no FTP site is always up, They are built to be reliable and we usually start to forget that they exist as we upload files daily year after year. Then someone changes a password, or the remote host changes the public key (why?), or just that the server the FTP is hosted on fails.
Suddenly our nice reliable bit of code is not working, the files are not being sent, the boss is on your back about the important data that needs to be sent to clients. After some investigation in those logs you are glad you set to verbose, you discover a SessionRemoteException, the remote FTP is bouncing the requests, after some toing and froing with the ftp host it turns out the password had been changed after they had a security scare and they had missed you off the notification list.
In any military plan of attack or defence, there has to be a fallback position, it is not the ideal, you don’t want to have to enact it, but it is a hell of a lot better to plan where to make your last stand or where evac is going to be, than having to decide in the midst of disaster.
In programming we have the same choice to make, decide your fallback position now, while you have full knowledge of your code and time to think calmly about a solution, or years later when you have forgotten what the code does and him in the next office is on the war path.
The Polly fallback solution
Now we could add in our own code to add in a fallback, perhaps catching the exception and sending an email out to ourselves, and in this simple example we may be best of doing this.
However if we are doing this in several places in our code, we will eventually want to extract the fallback from our code and write a utility class that will control this fallback for us and soon we may have well just used the fully tested and well maintained library that is Polly.
As a simple example lets add Polly to our solution from before.
- We handle or catch the exception – on a side note we can chain these handles so that we could handle several different exception types.
- We add an action to the fallback to send an email if our file upload function throws the exception listed.
- We add our Upload function to the fallback’s execute function.
Note: In this simple example I have removed code that would make the solution look too bulky, so imagine the parameters have been set.
One better – Policy wrap
In last week’s post I used wait and retry, imagine if we could use both retry and fallback, as the exception could be caused by a momentary blip in connection to the FTP. Well prepare to be spoiled, because you are going to get all you wished for!
Polly has in 5.0+ at least something called a policy wrap, where you can add several policy’s together.
var fileUploadResult = Policy.Wrap(fallback, waitAndRetry).Execute(action);
All you need to do is to define your policies, and list them in the order you want them implemented, left to right. In our example waitAndRetry will be called first, and then fallback once the retries have been exhausted.
For more details see the Github documentation for Policy Wrap
Nice as it is to have Polly code to add into our classes, at some point it is going to get messy if we have it dropped all over the place. Imagine if we could define a policy for an exception and use this across our code base. Well Polly doesn’t disappoint, the creators have thought of this as well – added in Polly 5.2.
PolicyRegistry registry = new PolicyRegistry();
For more details see the Policy Registery documentation on Github
We have explored some of the capabilities of Polly in helping us to create fallback positions in our code when things go wrong.
- We have used the fallback function to catch an exception and reroute the flow to a fallback action.
- We have looked at Policy wraps allowing us to chain together several policies, allowing us to create more intelligent fault handling responses.
- We have looked at the Policy Register allowing us to create policies centrally and reuse across our code base.