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
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare la session affinity con Azure Container Apps
Migrare una service connection a workload identity federation in Azure DevOps
Configurare dependabot per aggiornare le dipendenze di terze parti con GitHub Actions
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Paginare i risultati con QuickGrid in Blazor
Gestire domini wildcard in Azure Container Apps
Utilizzare i primary constructor in C#
Limitare le richieste lato server con l'interactive routing di Blazor 8
Eseguire operazioni sui blob con Azure Storage Actions
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Recuperare un elemento inserito nella cache del browser tramite API JavaScript
Come migrare da una form non tipizzata a una form tipizzata in Angular
I più letti di oggi
- C# 4
- Spaziatura tra i caratteri in Silverlight 5
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Segui in tempo reale il TechEd 2004
- da oggi è possibile fare login velocemente con LinkedIn e Google. a questi si aggiunge il supporto già attivo per Facebook, Twitter, Microsoft Account, Windows Hello e OpenID, per darvi sempre più possibilità di accedere semplicemente alla nostra community! #aspitalia
- Migrare una service connection a workload identity federation in Azure DevOps
- Evitare postback multipli in un UpdatePanel