super_cache
Cache LRU et TTL pour Flutter et Dart, avec stockage en couches et protection contre les appels redondants.
Une bibliothèque de cache pour Flutter et Dart qui supprime les appels API en double, évince en O(1) et expose le taux de succès en direct. Aucune dépendance externe dans le cœur.
super_cache est une bibliothèque de cache pour Flutter et Dart, publiée sur pub.dev sous licence MIT. Le cœur ne dépend d'aucun paquet externe et fonctionne sur Android, iOS, Web, macOS, Windows et Linux.
Elle existe pour un problème précis : trois widgets qui demandent le même utilisateur au même instant déclenchent trois appels réseau identiques. super_cache les regroupe en un seul. Une clé déjà en cours signifie une seule requête, et tous les appelants attendent la même future.
Autour de ce mécanisme : un LRU en O(1) avec TTL, trois couches de cache qui font remonter les entrées lors d'un succès, et des métriques lisibles pendant l'exécution.
Fonctionnalités clés
LRU en O(1) avec TTL
Une table de hachage associée à une liste doublement chaînée maintient get, put et éviction à temps constant quelle que soit la taille. Le TTL fonctionne en mode absolu ou glissant par entrée : un jeton de session et une liste de produits peuvent donc expirer selon des règles différentes dans le même cache.
Protection contre les requêtes redondantes
Les lectures concurrentes d'une clé déjà en cours partagent une seule future au lieu de déclencher chacune sa requête. Trois widgets montés en même temps produisent un seul appel réseau.
Trois couches avec promotion
Mémoire, tampon chiffré en AES-256-GCM, puis disque avec un fichier par entrée. Un succès sur le disque fait remonter l'entrée à travers les couches : la lecture suivante se fait en mémoire.
Des politiques par appel
CacheAside lit paresseusement, WriteThrough récupère toujours des données fraîches, et RefreshAhead sert la valeur périmée pendant qu'elle se rafraîchit en arrière-plan. La politique est un argument, pas un réglage global.
Des métriques observables
Taux de succès, nombre d'évictions et nombre d'entrées sont disponibles en instantané ou en flux diffusé : le comportement du cache s'observe à l'exécution au lieu de se deviner depuis les journaux réseau.
Des tests déterministes
Un paquet compagnon fournit FakeCache et ManualClock, ce qui permet de tester l'expiration TTL et l'éviction sans faire dormir la suite de tests.
Stack technique
Architecture
Trois couches se placent derrière un orchestrateur unique. L1 est un LRU en mémoire, synchrone en cas de succès. L2 est un tampon en mémoire chiffré en AES-256-GCM. L3 est un stockage disque avec un fichier par entrée et validation d'intégrité. Une lecture descend de L1 vers L2 puis L3 et fait remonter ce qu'elle trouve, si bien que les lectures répétées finissent en mémoire.
L'API renvoie FutureOr<V?> plutôt qu'une Future systématique. Un succès en L1 se résout de façon synchrone et ne cède jamais la main à la boucle d'événements, ce qui maintient une lecture mémoire autour de 0,04 microseconde au lieu de payer un saut asynchrone pour une valeur déjà disponible.
L'éviction peut se piloter par nombre d'entrées ou, avec un sizeEstimator, par octets. Un point d'accroche evictFraction() permet aussi de libérer une partie du cache quand la plateforme signale une pression mémoire, au lieu d'attendre d'être tué.
Le paquet principal ne dépend de rien hors du SDK. Chiffrement, persistance disque et doublures de test vivent dans des paquets compagnons : une application qui ne veut qu'un LRU en mémoire n'embarque pas flutter_secure_storage.
Défis & Solutions
Les problèmes complexes, et comment je les ai résolus.
Garder un succès mémoire hors de la boucle d'événements
Rester honnête sur ce que protège la couche chiffrée
Plus de projets
Intéressé par une collaboration ?
Je suis toujours ouvert à discuter de nouveaux projets et opportunités.