← Tous les projets
En vedette Open Source 2026

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.

#dart#flutter#caching#lru#open-source#pub-dev

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

DartFlutterLRUTTLAES-256-GCM

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.

01

Garder un succès mémoire hors de la boucle d'événements

Faire de chaque lecture une Future est la conception évidente, et elle coûte un passage par la boucle d'événements sur des valeurs déjà en mémoire. Renvoyer FutureOr permet à un succès L1 de se résoudre de façon synchrone : 0,04 microseconde par lecture mesurée, contre 0,22 dès que l'orchestrateur ajoute une couche asynchrone. En contrepartie le type est un peu plus lourd aux points d'appel, ce que le mixin de dépôt masque.
02

Rester honnête sur ce que protège la couche chiffrée

SecureCache chiffre les valeurs au repos en mémoire, mais les valeurs déchiffrées restent dans le processus. Parler de stockage sécurisé serait une affirmation fausse : la documentation précise donc clairement qu'il ne s'agit pas d'une protection par enclave matérielle. Le README liste aussi les cas où le paquet est le mauvais outil : moins de cinq valeurs, accès multi-isolats, ou objets au-delà de 50 Mo, où une base locale répond mieux.

Intéressé par une collaboration ?

Je suis toujours ouvert à discuter de nouveaux projets et opportunités.