Impostare retry automatici nella chiamata a un servizio in ASP.NET Core MVC

di Marco De Sanctis, in ASP.NET Core,

Un'applicazione robusta deve essere disegnata in modo da tenere in considerazione che le risorse esterne a cui accediamo, siano esse database o servizi, possano temporaneamente fallire. Questo è soprattutto vero in uno scenario cloud, in cui la stessa natura disconnessa dell'ambiente può essere causa di questi fault.

Spesso si tratta di problemi che durano lo spazio di qualche millisecondo, per cui, prima di restituire un messaggio di errore all'utente, può valere la pena effettuare un nuovo tentativo. Piuttosto che scrivere a mano il codice necessario, possiamo sfruttare una libreria come Polly: si tratta di un package NuGet che mette a disposizione una serie di primitive per gestire questo tipo di necessità.


Immaginiamo allora di avere un'interfaccia IContentService che astragga una chiamata al database o a una generica risorsa esterna:

public interface IContentService
{
  Task<string[]> LoadArticlesAsync();
}

Normalmente, il nostro codice sul controller sarebbe qualcosa di simile al seguente:

private IContentService _content;

public async Task<IActionResult> Index()
{
    var articles = await _content.LoadArticlesAsync();

    return View(articles);
}

Ovviamente, in questo modo, una singola eccezione sulla connessione, causerebbe un errore e quindi una risposta di StatusCode 500 restituita all'utente.

Cerchiamo di capire come possiamo rendere allora l'applicazione più robusta. Il concetto base di Polly è rappresentato dalla classe Policy, tramite la quale possiamo specificare il comportamento che desideriamo implementare. Nel nostro caso, vogliamo effettuare in automatico qualche Retry, prima di fallire definitivamente.

public async Task<IActionResult> Index()
{
    var policy = Policy
        .Handle<Exception>()
        .RetryAsync(retryCount:3);

    var articles = await policy.ExecuteAsync(
        () => _content.LoadArticlesAsync());

    return View(articles);
}

La fluent interface di Polly rende tutto estremamente leggibile e chiaro: tramite il metodo Handle abbiamo specificato che vogliamo gestire ogni possibile eccezione, ma ovviamente è possibile isolarne alcune specifiche. Successivamente, con RetryAsync, abbiamo indicato che vogliamo riprovare al massimo per 3 volte. Esistono diversi overload di questo metodo, alcuni con un callback che viene invocato automaticamente a ogni retry, così che possiamo per esempio loggare comunque l'errore.

L'ultimo step è la chiamata a ExecuteAsync, alla quale abbiamo passato il metodo effettivamente da eseguire.

Il codice in allegato mostra il tutto in funzione, con un'implementazione fittizia di IContentService che restituisce una risposta con successo solo al terzo tentativo.

Questo è solo un utilizzo basilare di Polly, nei prossimi script daremo un'occhiata a ulteriori funzionalità, utilissime per rendere più robusta la nostra applicazione.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi