AngoraTek EN
← Retour au blog
Notes de terrain 7 min de lecture

Le cache de tuiles qui n'oublie jamais

À dix minutes au sud de South Lake Tahoe, la route vers le départ du sentier entre dans une zone blanche et le téléphone passe d'une barre de signal à aucune. Le randonneur au pied du sentier a toujours sa carte : courbes de niveau, sentiers, ligne d'itinéraire, le tout rendu sur l'appareil depuis le petit-déjeuner. Pas de spinner, pas de toast « vous êtes hors ligne ». La carte venait d'un cache à qui personne n'a jamais dit que quoi que ce soit expire.

WayMaker, le planificateur d'itinéraires de randonnée que nous développons, rend les tuiles de fond de carte d'OpenTopoMap et d'OpenFreeMap et les stocke dans un cache de service worker sans date d'expiration ni politique d'éviction. Une tuile en cache reste valable pour toujours, alors le cache la garde pour toujours. Lue comme une décision d'architecture web, cette phrase ressemble à un défi. Pour un produit dédié aux sentiers, c'est la bonne lecture de ce qu'est une tuile. L'ingénierie qui mérite qu'on en parle se trouve dans les coûts que nous avons acceptés en même temps que cette décision et dans la soupape unique qui garde ce montage viable.

Sur un sentier, le hors-ligne est le cas par défaut

La plupart des applications web traitent le hors-ligne comme un cas limite qui hérite d'un écran de repli, et ce traitement est honnête : leurs utilisateurs sont presque toujours à portée d'un réseau. La journée d'un randonneur inverse le rapport. L'itinéraire se planifie à la maison sur le Wi-Fi, peut-être formulé en langage courant : « une boucle ombragée de 10 km près de Tahoe avec vue sur le lac », et il se parcourt à une vallée du routeur le plus proche. Téléphone en poche, écran éteint, session qui tourne des heures sans réseau : voilà les conditions d'exploitation, pas l'exception.

Être installable est le minimum vital, ici. WayMaker est livré en PWA, il vit donc sur l'écran d'accueil comme les applications de randonnée que les gens portent déjà, et le service worker est ce qui décide si le deuxième jour d'un voyage a encore une carte. Un mode hors-ligne commercialisé comme un feature flag reviendrait à prétendre que le moment le plus important d'une carte est optionnel. Nous avons pris le parti inverse : le hors-ligne est le chemin principal, et la connectivité, le bonus.

Une tuile en cache reste valable pour toujours, et ce fait supprime l'expiration

Demandez-vous ce qui change dans une tuile de fond de carte, et à quelle échelle de temps. Une tuile est un rendu de données ouvertes (points et voies d'OpenStreetMap, couches dérivées d'OpenTopoMap, styles d'OpenFreeMap), couvrant quelques centaines de mètres de terrain. Ce rendu change au rythme des données cartographiques : recheminements de sentiers, coupes forestières, fermetures saisonnières arrivent à l'échelle des mois. Quand l'une d'elles arrive, la conséquence pour un randonneur qui regarde une tuile vieille de quelques mois est quasi nulle. Une tuile n'a pas d'horloge en elle. Ce n'est pas un cours de bourse ; sa vérité se désagrège à la vitesse du monde physique, ce qui, pour un coin de nature, est glaciaire.

Cet argument est ce qui supprime l'expiration. Si la justesse se dégrade lentement, une date d'expiration n'achète rien, et l'éviction facture un retéléchargement plus un carré blanc de carte à exactement le mauvais moment. Alors le cache garde tout ce qu'il a jamais récupéré.

La limite honnête se trouve à côté de l'argument, pas après lui. Un fond de carte vieillit bel et bien de façon visible : la route postérieure à la tuile n'y sera pas, aussi sûre que paraisse la ligne d'itinéraire qui la franchit. Nous assumons cette péremption. Face à l'alternative, un carré blanc dans une vallée à 18:00, nous assumerions encore cette péremption.

Deux caches, parce que deux sortes de données échouent différemment

Le premier réflexe de tout service worker, c'est un cache, une politique. Dans WayMaker, les deux grandes sortes de contenus ne pouvaient pas en partager un.

Le shell de l'application (documents, JavaScript, styles, polices) est un artefact versionné. Servir un ancien shell depuis le cache pour toujours crée la panne classique de désynchronisation de versions : un ancien bundle qui appelle des points d'entrée dont la forme a évolué, une interface à moitié mise à jour contre elle-même. Les requêtes de navigation tournent donc en network-first avec un repli hors-ligne, ce qui veut dire un shell neuf dès qu'il y a du réseau et le shell en cache à l'instant où il n'y en a plus.

Les tuiles tournent en cache-first, pour la raison de la section précédente. Deux caches, deux pannes évitées : la désynchronisation de versions d'un côté, une carte blanche dans une vallée de l'autre. La scission a été le pivot. Dès que nous avons cessé de faire semblant qu'une seule politique pouvait gouverner les deux, le design a cessé de nécessiter des exceptions.

Le prix, c'est le stockage, et la soupape, c'est CLEAR_MAP_DATA

L'arbitrage oppose le stockage à la bande passante, et nous avons choisi le stockage sans plafond. Chaque région qu'un utilisateur a parcourue un jour garde ses tuiles, le cache grossit de façon monotone avec la curiosité, et rien ne s'en décharge de lui-même. L'économie de bande passante est réelle et récurrente : aucune tuile que l'utilisateur a déjà payée une fois n'est payée deux fois. Face à cela se dresse un risque que nous ne contrôlons pas entièrement : les navigateurs plafonnent les quotas de stockage et, sous pression, ils peuvent vider des caches de leur propre jugement, rayant la garantie hors-ligne à notre insu et sans notre accord.

Notre réponse aux deux a été de tout garder et de remettre la soupape à l'utilisateur. Un canal de messages vers le service worker efface les données de carte, et rien d'autre.

// the valve, reduced to its message
navigator.serviceWorker.controller.postMessage({ type: 'CLEAR_MAP_DATA' });

Un utilisateur qui a passé une année à trimballer trois régions de tuiles peut libérer l'espace en un seul appui et garder chaque itinéraire sauvegardé et l'état de son compte. Le retéléchargement ne coûte que la seule région qui compte pour le prochain départ, celle qui se trouve en ce moment sous ses pieds. La soupape est manuelle, et ce caractère manuel est un choix délibéré. L'éviction automatique est précisément le mécanisme qui produit des cartes blanches, et nous n'étions pas prêts à laisser le cache prendre cette décision pendant que quelqu'un se tient sur un sentier.

Les liens de partage expirent au bout de sept jours, exprès

L'oubli délibéré vit côté serveur. Les liens de partage de WayMaker cessent de se résoudre après 7 jours, au serveur, exprès. Ce choix est l'image miroir du cache de tuiles, et c'est ce qui rend défendable la décision de ne rien oublier côté carte. Un itinéraire partagé est une conversation entre deux personnes, pas une archive : le destinataire l'ouvre, copie le GPX, et passe à autre chose en moins d'une semaine. L'expiration dit aussi quelque chose de vrai, à la personne qui partage, sur la garde des données. Vos plans et vos traces ne s'accumulent pas sur notre serveur par défaut. Une fonctionnalité avec état hébergée pour toujours devient un passif : du stockage qui ne cesse jamais de croître, et l'obligation discrète de continuer à la maintenir.

Ce que nous referions autrement

Nous n'avons pas livré de compteur de taille. Le cache ne peut pas dire à l'utilisateur quelle part de son téléphone il occupe. Le premier acteur à prononcer le mot « stockage » à voix haute, c'est l'éviction du navigateur lui-même, qui arrive sans consulter et emporte la garantie hors-ligne. Si nous refaisions l'écran de réglages cette semaine, il afficherait le compteur à côté de la soupape, rafraîchi à l'ouverture de l'application, avec une ligne claire désignant les régions qui portent la masse. De tous nos choix, c'est celui-là qui pique un mardi ordinaire, pas sur un sentier. Leçon retenue : un cache sans politique a plus besoin d'un tableau de bord que d'une politique, parce que le compteur rend l'arbitrage visible au moment où il se fait.

Un cache qui n'oublie jamais est correct partout où l'oubli n'a pas de valeur. Les tuiles de fond de carte d'un sentier passent ce test, les liens de partage le ratent exprès, et la distance entre ces deux phrases est tout le design. Décidez de quelle sorte de données vous détenez avant de décider combien de temps les détenir.

Merci d'avoir lu jusqu'ici. Si cela ressemble au problème sur lequel vous butez, parlez-nous-en. Un fondateur lit chaque message.

Engager la conversation