LazyCaching avec .NET

Niveau :

9 minutes de lecture

Dans cet article, vous allez apprendre à accélérer vos développements en implémentant une gestion de cache local ainsi :

  • Pourquoi un cache local ?
  • Prérequis
  • LazyCache avec injection de dépendances
  • Gérer le cache (durée, suppression, …)

Pourquoi un cache local ?

Imaginons un scénario assez courant comme le développement d’une application utilisant beaucoup de ressources et générant des temps assez conséquent lors de la récupération de certaines données. Les équipes ont donc l’habitude de mettre en place une gestion de cache dédié, mais souvent en environnement de production car cela peut être couteux (encore plus quand on déploie sur le cloud).

Cela se traduit par des temps de développements et de tests de plus en plus long et qui s’alourdit dans le temps. Pourquoi ne pas mettre en place rapidement un système de cache local ?

LazyCache vous permet de faire tout cela de manière simple et optimisé

Prérequis

  • Un projet web comme par exemple le template API web ASP.NET Core
  • Un autre projet de type console .NET

LazyCache sans injection de dépendances

Dans le projet de type console, ajoutez le package NuGet LazyCache :

Créez une nouvelle classe qui simulera un processus de récupération de données assez long. Cette classe contient une temporisation de 5 secondes avant de renvoyer une liste de string :

namespace LazyCacheWithNetWithoutDI
{
    internal static class LongTaskAndResources
    {
        internal static async Task<List<string>> GetLongTask()
        {
            await Task.Delay(5000);
            return new List<string>() { "val1", "val2", "val3" };
        }
    }
}

Dans la classe Program.cs, rajoutez la gestion du cache en déclarant une fonction pour configurer l’appel à GetLongTask() comme ci-dessous :

using LazyCache;
using LazyCacheWithNetWithoutDI;

IAppCache cache = new CachingService();

//Function pour appeler la longue tache mais ne l'exécute pas ici
Func<Task<List<string>>> stringGet = async() => await LongTaskAndResources.GetLongTask();

//on exécute la fonction et on la met en cache
var stringsWithCaching = await cache.GetOrAddAsync("stringKey", stringGet);

Console.WriteLine($"{stringsWithCaching.Count} strings trouvés");

Si vous exécutez le programme, l’appel s’effectue au bout de 5 secondes et vous renvoi le nombre de strings trouvés.

Rajoutez un timer et un nouvel appel à la fonction pour vérifier que le cache fonctionne correctement comme ci-dessous :

using LazyCache;
using LazyCacheWithNetWithoutDI;

IAppCache cache = new CachingService();

//Function pour appeler la longue tache mais ne l'exécute pas ici
Func<Task<List<string>>> stringGet = async() => await LongTaskAndResources.GetLongTask();

//on exécute la fonction et on la met en cache
var timer = new System.Diagnostics.Stopwatch();
var stringsWithCaching = await cache.GetOrAddAsync("stringKey", stringGet);
timer.Stop();
Console.WriteLine($"{stringsWithCaching.Count} strings trouvés en {timer.Elapsed.TotalSeconds} seconde(s)");

//on exécute la fonction une nouvelle fois
timer.Restart();
stringsWithCaching = await cache.GetOrAddAsync("stringKey", stringGet);
timer.Stop();
Console.WriteLine($"{stringsWithCaching.Count} strings trouvés en {timer.Elapsed.TotalSeconds} seconde(s)");

Exécutez le programme et constatez que le second appel ne prends plus 5 secondes mais est quasiment instantanée :

LazyCache avec injection de dépendances

Dans le projet de type web, ajoutez le package NuGet LazyCache.AspNetCore :

Récupérer la classe qui permet de simuler le long processus de récupération de données. Nous l’utiliserons dans le controller plus tard. Dans la classe Program.cs, rajoutez l’utilisation du cache comme ci-dessous :

// Add services to the container.
builder.Services.AddLazyCache();

Dans le controller WeatherForecastController.cs, rajoutez la gestion du cache comme ci-dessous via l’injection de dépendances :

using LazyCache;
using Microsoft.AspNetCore.Mvc;

namespace LazyCacheWithNet.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly IAppCache _cache;

        public WeatherForecastController(IAppCache cache)
        {           
            _cache = cache;
        }

        [HttpGet(Name = "GetWeatherForecast")]
        public async Task<ActionResult<List<string>>> Get()
        {
            Func<Task<List<string>>> stringGet = async () => await LongTaskAndResources.GetLongTask();
            var result = await _cache.GetOrAddAsync("stringKey", stringGet);
            return result;
        }
    }
}

Exécutez le programme et constatez que le second appel ne prends plus 5 secondes mais est quasiment instantanée :

Gérer le cache

Gérer la durée

La durée par défaut du cache est de 20 minutes. Vous pouvez changer cela au niveau des appels comme ceci (ici on met en cache pour une durée de 5 minutes) :

//Cache de 5 minutes
var result = await _cache.GetOrAddAsync("stringKey", stringGet, TimeSpan.FromMinutes(5));

Vous pouvez aussi le faire de manière « glissante » comme ceci :

//Cache de 5 minutes
var result = await _cache.GetOrAddAsync("stringKey", stringGet, DateTimeOffset.Now.AddMinutes(5));

Supprimer des éléments du cache

Vous pouvez supprimer un élément du cache de cette manière :

_cache.Remove("stringKey");

Retrouver un élément dans le cache

Vous pouvez retrouver un élément dans le cache comme ceci :

var mesStrings = _cache.Get<List<string>>("stringKey");

Vous pouvez retrouver dans ce lien d’autres exemples sur la gestion du cache.

Laisser un commentaire