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
Usare Refit e Polly in Blazor per creare client affidabili e fortemente tipizzati
Ottimizzare la latenza in Blazor 8 tramite InteractiveAuto render mode
Utilizzare il trigger SQL con le Azure Function
Migrate and Modernize your .NET Applications on Azure
Elencare le container images installate in un cluster di Kubernetes
Personalizzare l'errore del rate limiting middleware in ASP.NET Core
Utilizzare Tailwind CSS all'interno di React: installazione
Modificare i metadati nell'head dell'HTML di una Blazor Web App
Load test di ASP.NET Core con k6
Eseguire operazioni sui blob con Azure Storage Actions
Autenticarsi in modo sicuro su Azure tramite GitHub Actions
Implementare il throttling in ASP.NET Core
I più letti di oggi
- Vuoi incontrare Bill Gates? Viaggia con ASPItalia.com!
- Customizzare il pager del DataGrid
- Stabilire un collegamento VPN tra una Web App e una Virtual Network
- Documentare ASP.NET Web API con Swagger
- Usare i servizi REST di BING per ottenere informazioni sulla posizione dell'utente
- Visual Studio 2005 CTP May