Implementing Retry pattern using Polly in .NET Core Application

Understanding Retry Pattern using Polly Nuget package

Yohan Malshika
Enlear Academy

--

When developing robust applications, handling transient faults that might occur due to network issues, service unavailability, or other intermittent problems is crucial. The Retry pattern is a reliable approach to address these transient faults by automatically re-attempting failed operations for a defined number of times until success or a specified timeout.

This article explores the implementation of the Retry pattern using Polly, a .NET resilience and transient-fault-handling library, within a .NET Core application. It will delve into understanding the Retry pattern, its advantages, an introduction to Polly, and a detailed walkthrough of its implementation.

Understanding Retry Pattern

The Retry pattern is a fault-tolerant mechanism that helps in dealing with transient failures by re-executing failed operations for a specified number of attempts. This approach enables developers to manage temporary glitches, such as network timeouts or intermittent service failures, by retrying the operation instead of immediately declaring a failure.

For instance, suppose one of the microservices experiences a memory overload issue or another problem, resulting in its downtime. We have the option to attempt retries with a specific delay or decide not to until we restart the microservice. This approach allows us to effectively handle the downtime problem. There are more real-world examples, in which we could use the retry pattern.

Why Retry Pattern is Important?

In today’s apps and systems, small hiccups or network problems can happen. These glitches can disrupt how things work. To keep things going smoothly, the retry pattern helps a lot. It’s like a backup plan that ensures things keep running even if there are some issues.

  • Handling Transient Faults: Addresses temporary faults like network glitches or resource unavailability by automatically retrying failed operations.
  • Enhancing Reliability: Improves system resilience by allowing applications to recover from momentary disruptions without manual intervention.
  • Improving User Experience: Shields users from encountering errors, providing a smoother and uninterrupted experience within the application.
  • Proactive Fault Handling: Proactively handles potential transient faults, strengthening the system’s overall resilience and reliability.
  • Adaptive Response: Configurable retry strategies adapt to varying service availability, optimizing operation completion.
  • Reducing Downtime: Prevents operational disruptions by persisting through transient faults, maintaining service availability for users.

What is Polly?

Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies, such as Retry, Circuit Breaker, and Timeout, to handle faults in a fluent and thread-safe manner. It provides an easy and declarative way to define and execute these policies to improve the reliability of applications.

Polly can be installed in a .NET Core Web application via NuGet Package Manager or Package Manager Console using the following command:

dotnet add package Polly

Implementing Retry Pattern with Polly in .NET Core Application

Here’s a simplified example of using Polly to implement a retry policy in a .NET Core Web App:

var httpClient = new HttpClient();

var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(15),
onRetryAsync: async (exception, timespan, retryAttempt, context) =>
{
Console.WriteLine($"Retry attempt {retryAttempt} after {timespan.TotalSeconds} seconds due to: {exception.Message}");
});


// Apply the retry policy to an API call
var result = await retryPolicy.ExecuteAsync(async () =>
{
var response = await httpClient.GetAsync("https://example.api.com/example-data");

// Check if the request was successful
response.EnsureSuccessStatusCode();

// Process the response if successful
var content = await response.Content.ReadAsStringAsync();
return content;
});

In this scenario, the code snippet showcases how the Retry pattern gets implemented using WaitAndRetryAsync method in Polly within a .NET Core application setup. It starts by setting up a HttpClient to perform the API requests. Then, a retry policy is defined using Polly's WaitAndRetryAsync method. This policy specifies that if an HttpRequestException occurs (commonly due to issues like network problems or unavailability of the API), the system should retry the request up to three times with a fixed delay of 15 seconds between each attempt.

For example, We are using https://example.api.com/example-data this API and it is not hosted. In that case, this should be retried 3 times automatically within a fixed delay.

This demonstrates how Polly actively simplifies the integration of resilience strategies like Retry within .NET Core Web app, empowering the system to gracefully manage transient failures and bolster its resilience against intermittent issues in API communications.

Exponential Backoff Strategy

Exponential backoff is a retry strategy where the delay between retries increases exponentially after each attempt. It aims to prevent overwhelming the failed resource with too many consecutive requests.

var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetryAsync: async (exception, timespan, retryAttempt, context) =>
{
Console.WriteLine($"Retry attempt {retryAttempt} after {timespan.TotalSeconds} seconds due to: {exception.Message}");
});

In the Exponential Backoff Strategy example, the delay between retries grows exponentially. Here, the sleep duration is calculated using TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)). The retryAttempt variable indicates the current attempt number, and the delay increases exponentially based on that number.

By employing exponential backoff, the system introduces an increasing delay, which can be more effective in reducing the load on a failing resource and allowing more time for recovery before subsequent retries, potentially improving the chances of a successful request.

Choose the strategy that best suits your application’s needs and resource constraints when dealing with transient faults and retries.

When to Use the Retry Pattern

  • Network Operations: Retry pattern is suitable for handling network-related operations where transient faults like timeouts or connectivity issues can occur.
  • External Service Calls: It’s useful when integrating with external services that might encounter intermittent failures.

When Not to Use Retry Pattern

  • Non-idempotent Operations: Avoid using Retry for non-idempotent operations (e.g., operations that modify data) as it may lead to unintended side effects on multiple retries.
  • Non-transient Failures: When dealing with permanent or non-recoverable failures, retries might exacerbate the issue.

Conclusion

Implementing the Retry pattern using Polly in a .NET Core Web application enhances the application’s resilience by handling transient faults gracefully. Polly’s simplicity and configurability make it a powerful tool for managing fault-handling strategies, thereby improving the reliability of applications in the face of intermittent failures. Understanding when to apply Retry and when to avoid it is crucial for leveraging its benefits effectively in different scenarios.

--

--