This week i want to highlight another excellent NUGET package i found on my travels called Polly. Polly is a fault handling library that allows you to apply retry attempts to remote call failures such as database connections or a HTTP request.
I stumbled across the package whilst reading Microservices in .NET Core (if you have an interest in micro-services i highly recommend this as a read) & immediately i was impressed by what it could do in a fluent code API manner making it tidy & succinct to read.
The library itself covers various ways of how you want to handle failure retry attempts, the more common API calls being the following:
- Retry again & repeat this cycle x amount of times before giving up.
- wait for x amount of seconds & retry again, repeating this cycle x amount of times before giving up (or until successful).
- wait for x amount of seconds & retry again, repeating this cycle forever until successful.
For this blog post i will cover a very simple example by fetching data from SQL & apply the first point above. Note that Polly has much much more features than those listed above, it can also provide circuit breaker and fallback handling, i haven’t tried these yet so i wont cover them in this post.
The easiest way to get up and running with Polly is to first identify an exception type that you need to apply fault handing for, lets go with an obvious one in this example by using SqlException, this will typically fail when a connection string is not valid, or the network is down, etc.
So first up, in red below i have declared a static property of Policy (from the Polly library) & using fluent API set the exception type we want to apply retry attempts on, the Retry function with parameter 1 is the actual policy & means if this exception is raised in an operation than please make 1 attempt to try again, …all nice & easy right?
Next up we apply the declared policy to a function, as per below in red. Notice the neatness which Fluent API brings to the code, again, all very readable. For this example i have wrapped the code in a try/catch which captures the error stack trace for the caller, you obviously don’t have to do this & could just let it bubble up to the caller.
PerformDatabaseReadById is just a helper method which is performing the SQL work for us as can be seen below (In case your not familiar with the db.Query<Person> syntax below, this was taken from a previous post i did on Dapper).
Everything is now in place to test the supreme power of fault handling by Polly. For this demo i have a console app which calls GetById and displays to the screen, if the call is not successful display an error.
To prove that Polly is indeed retrying, i have added a console output in green colour for when the SQL fetch method is being called by Polly. In this instance everything was successful & only one call was made to fetch the data (note the one green trace output).
Now the acid test, we will invalidate the connection string with an extra character & force the policy to kick in & retry once after initial capture of the SqlException. Running the app again we will now get a failure message on screen but only after Polly has attempted to retry once & then give up before finally displaying the SqlException message, note the two green text outputs to indicate one normal call & one retry attempt..pretty cool right!
I have made extensive use of the package in my latest project, where i have wrapped the library calls around SQL database & RabbitMQ connections & it has met those needs perfectly.
It gives great confidence to you the developer knowing that resiliency is now well handled in your application and is totally configurable without any significant effort at all, that is a huge win in my eyes. I have only covered a tiny bit of what the framework has to offer but hopefully i have convinced you a little to explore it some more & start applying it in your own mission critical projects.
All the code samples above are available on my GitHub page so please free to dissect at your leisure.
So now, plenty of reasons to be chirpy about the resiliency of your application code!