Retry OData Client calls with Polly in .NET 4.5

See the source image

Polly is a powerful fault handling library which can help make your service calls more resilient to failure.  Polly makes it very easy to define policies for service call retries, timeouts, circuit breaking and fallbacks that configure against your service client in a fluent way.

We use Polly in our serverless microservice architecture extensively to make our service integrations more resilient and it works really well.  There is a bit of a learning curve to these fault handling patterns and how to set them up the right way for your system but it is well worth it.  Fault handling for services is a core capability of microservice architectures.

Cold Start Performance Issues

Recently we had a need to use some of our microservices from a legacy .NET 4.5 application.  Initially we simply created an OData client against our microservice and that worked but we found the service calls were slow and had a high failure rate when running at scale.

The root cause was our serverless execution model.  AWS Lambda has to spin up small containers behind the scenes to perform serverless execution (see previous cold start blog posts).  This ultimately delays the service response and creates a poor experiences especially for UI related usages.

This issue is circumvented in our new architecture by setting up Polly retry policies with a short timeout.  We do this in our shared .NET Core base classes which are used by all our services.  We don’t use these base classes in our legacy app however.

.NET 4.5 OData Client

In .NET Core the OData Client allows overriding the HttpClient via the fluent middleware APIs (AddODataClient/AddHttpClient).  In .NET 4.5, however,  this is less straight forward.

We are currently using version 7.6.3 of the Microsoft.OData.Client Nuget package.

In order to extend/customize the HttpClient behavior you must override the OnMessageCreating method of the DataServiceContext.

var message = new HttpClientRequestMessage(args.ActualMethod, pollyPolicy) { Url = args.RequestUri, Method = args.Method, };
foreach (var header in args.Headers)
{
     message.SetHeader(header.Key, header.Value);
}

return message;

You must also define a class which derives from the abstract class DataServiceClientRequestMessage.  The derived class must implement multiple properties/methods and in the GetReponse methods we will wrap the HTTP calls with the Polly policy:

return System.Threading.Tasks.Task.Run(() =>
   pollyPolicy.Execute(() => {
      …
   })
);

You can find the full class here – https://gist.github.com/rschiefer/fec2684a428efb089ba399e7390600d0

This is by no means meant to be a perfect implementation.  There are likely multiple ways to improve this class but I wanted to share our first take at getting Polly to work with OData clients in .NET 4.5. 

With this configuration in place our DataServiceContexts perform service calls with the configured Polly policies in place performing retries and timeouts to improve the overall performance of the clients.

I hope this post helps others setup Polly faster with OData Clients in .NET 4.5.  If you see obvious opportunities for improvement please do leave a comment below and share it with me and the larger community.

Happy Retrying!

Leave a Reply