Utiliser AsyncExpiringLazy pour une mise en mémoire de données qui peuvent expirer

Je ne sais pas si c’est comme ça pour vous. Il y a quelques petits bouts de technologie que j’ai dans une liste que j’ai nommée « j’aimerais bien l’essayer un jour si le contexte s’y prête bien ». La liste est plus longue que d’occasions que j’ai de la mettre en oeuvre.

Au moins, la liste existe!

Cependant, il y a un peu d’espoir pour mes rêves. Dans le cadre d’un projet, j’ai eu à revisiter le scénario de la mise en cache des éléments récupérés d’un service externe. Ça a été la parfaite occasion de sortir l’utilitaire AsyncExpiringLazy de ma manche!

Puisqu’il s’agissait d’une liste de personnes utilisée au cœur de l’application, assez volumineuse et longue à récupérer. Je me devais de mettre en place un processus de mise en cache. De plus, par sa nature humaine, cette liste était amenée à changer avec le temps. Elle se devait d’être rafraîchie périodiquement avec des nouvelles données.

Ce qui est intéressant avec AyncExpiringLazy est justement dans son nom. À la base, il s’agit d’une classe qui a le même fonctionnement que la classe Lazy<T> de .NET. Son code d’accès aux données ne sera pas exécuté tant et aussi longtemps qu’elle n’est pas appelée. L’autre chose, c’est que, par configuration, sa mise en mémoire a une date de péremption. Une fois ce délai atteint, un rafraîchissement des données sera à nouveau exécuté.

Le bonus est que le tout tire profit du mécanisme async de .NET. Dans bien des contextes, avec ASP.NET, son utilisation est utile. C’est surtout que cela permet de permettre de rendre l’appel à mon API qui prend du temps moins bloquant pour les autres requêtes en traitement.

Comment ça marche?

Un gist vaut mille mots.


class CarsCache
{
private AsyncExpiringLazy<List<Car>> Cars { get; set; }
public CarService CarService { get; set; }
public CarsCache()
{
Cars = new AsyncExpiringLazy<List<Car>>(async metadata =>
{
return await Task.Run(() =>
{
return new ExpirationMetadata<List<Car>>
{
Result = CarService.GetAllCars(),
ValidUntil = DateTimeOffset.UtcNow.AddHours(12)
};
});
});
}
public Task<List<Car>> GetAllCars()
{
return Cars.Value();
}
}
// Par la suite, l'appel se fait ainsi
var cache = new CarsCache();
var cars = await cache.GetAllCars();

view raw

CarsCache.cs

hosted with ❤ by GitHub

Évidemment, le premier accès sera plus lent. Par la suite, la magie de AsyncExpiringLazy fera en sorte que vous pourrez accéder à vos données tant et aussi longtemps que le délai d’expiration ne sera pas atteint. Dans mon cas, je me suis aussi assuré que la cache soit toujours « chaude » en ajoutant une tâche avec FluentScheduler qui exécute périodiquement CarsCache().GetAllCars().

La dernière chose que vous devrez réaliser est d’utiliser votre librairie d’injection de dépendances afin de faire persister CarsCache à travers la durée de vie de votre application. Par la suite, le tour est joué!

Publicité

Auteur : Pascal Paradis

Je suis les mains et le cerveau derrière http://frenchcoding.com. Je développe des microservices chez @UbisoftMTL. Amateur de Hockey et j'aime la technologie, en général.

Laisser un commentaire

Entrer les renseignements ci-dessous ou cliquer sur une icône pour ouvrir une session :

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.

%d blogueueurs aiment cette page :