logo

Implementación del Retry Pattern en .NET 10: Construyendo Aplicaciones Resilientes


En el desarrollo de software moderno, los fallos transitorios —como una pérdida momentánea de conectividad, un timeout de red o un servicio externo saturado— son inevitables. El Retry Pattern (Patrón de Reintento) permite que una aplicación gestione estas interrupciones de forma transparente, reintentando una operación fallida un número determinado de veces antes de desistir. En este artículo, analizamos cómo implementar este patrón en .NET 10 utilizando las últimas mejoras en las librerías de resiliencia de Microsoft.

1. ¿Qué es el Retry Pattern?

El patrón de reintento es una estrategia de estabilidad que permite a un sistema recuperarse automáticamente de errores temporales. Su funcionamiento es sencillo: si una operación falla, el sistema espera un tiempo determinado y vuelve a intentarlo.

Existen tres estrategias comunes:


2. Configuración en .NET 10 con Microsoft.Extensions.Resilience

A partir de las versiones más recientes de .NET, Microsoft ha integrado profundamente las estrategias de resiliencia. Ya no es estrictamente necesario configurar Polly de forma aislada, sino que podemos usar el paquete estándar de resiliencia.

Instalación de dependencias

Bash

dotnet add package Microsoft.Extensions.Http.Resilience

3. Implementación Práctica: Cliente HTTP con Reintentos

Supongamos que nuestra aplicación consume una API de facturación que presenta micro-cortes ocasionales. Configuraremos un pipeline de reintento con espera exponencial y jitter (una variación aleatoria para evitar que múltiples instancias reintenten exactamente al mismo tiempo).

C#

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http.Resilience;
using Polly;

var services = new ServiceCollection();

services.AddHttpClient("FacturacionAPI", client =>
{
    client.BaseAddress = new Uri("https://api.ejemplo.com/");
})
.AddStandardResilienceHandler(options =>
{
    // Configuración del Retry dentro del pipeline estándar
    options.Retry.MaxRetryAttempts = 3;
    options.Retry.BackoffType = DelayBackoffType.Exponential;
    options.Retry.UseJitter = true;
    options.Retry.Delay = TimeSpan.FromSeconds(2);
});

4. Uso de Resilience Pipelines para Lógica de Negocio

Si necesitamos aplicar reintentos a una lógica que no sea estrictamente HTTP (por ejemplo, una consulta a base de datos o una escritura en disco), podemos definir un pipeline genérico:

C#

var pipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions
    {
        ShouldHandle = new PredicateBuilder().Handle<TimeoutException>(),
        MaxRetryAttempts = 4,
        Delay = TimeSpan.FromSeconds(1),
        BackoffType = DelayBackoffType.Constant,
        OnRetry = args =>
        {
            Console.WriteLine($"Intento {args.AttemptNumber} fallido. Reintentando...");
            return default;
        }
    })
    .Build();

// Ejecución de la tarea protegida
await pipeline.ExecuteAsync(async token => 
{
    await MiMetodoCriticoAsync(token);
});

5. Consideraciones de Diseño y Buenas Prácticas

Aunque el patrón de reintento es potente, debe usarse con cautela:

Conclusión

La implementación del Retry Pattern en .NET 10 es más sencilla y legible que nunca. Al adoptar estas estrategias, transformamos aplicaciones frágiles en sistemas robustos capaces de soportar la inestabilidad inherente a los entornos de nube y microservicios, mejorando significativamente la experiencia del usuario final.