Back to flin
flin

Le patron de trait StorageBackend

Une plongée en profondeur dans le trait StorageBackend de FLIN -- l'abstraction Rust qui rend quatre backends de stockage de fichiers interchangeables sans changer une seule ligne de code applicatif.

Juste A. Gnimavo (Thales) & Claude | March 26, 2026 3 min flin
EN/ FR/ ES
flinrusttraitsstorageabstractionarchitecture

Les abstractions sont faciles à mal concevoir. Vous les rendez soit trop fines -- exposant des détails spécifiques au backend qui fuient à travers chaque site d'appel -- soit trop épaisses, cachant des capacités dont le code en aval a légitimement besoin. Le trait StorageBackend dans FLIN devait naviguer précisément cet fil : suffisamment abstrait pour que les systèmes de fichiers locaux, S3, Cloudflare R2 et Google Cloud Storage s'intègrent tous derrière la même interface, et suffisamment concret pour que chaque backend puisse optimiser ses opérations sans contorsions.

La définition du trait

Le trait complet a neuf méthodes. Chacune a été choisie parce que les quatre backends en ont besoin, et aucune ne pouvait être exprimée purement en termes des autres :

rustpub trait StorageBackend: Send + Sync {
    fn put(&self, hash: &str, data: &[u8], extension: &str) -> StorageResult<String>;
    fn put_from_path(&self, hash: &str, temp_path: &str, extension: &str) -> StorageResult<String>;
    fn get(&self, path: &str) -> StorageResult<Vec<u8>>;
    fn delete(&self, path: &str) -> StorageResult<()>;
    fn exists(&self, hash: &str, extension: &str) -> StorageResult<bool>;
    fn url(&self, hash: &str, extension: &str) -> String;
    fn signed_url(&self, hash: &str, extension: &str, duration: Duration) -> StorageResult<String>;
    fn backend_type(&self) -> &'static str;
    fn base_path(&self) -> &str;
}

Pourquoi Send + Sync

Les deux mots les plus importants dans la définition du trait ne sont pas des noms de méthodes -- ce sont Send + Sync. Ces traits marqueurs Rust garantissent que tout type implémentant StorageBackend peut être partagé entre les threads et envoyé à travers les frontières de threads de manière sûre.

Le patron Arc<dyn StorageBackend> -- un objet trait à comptage de références atomique -- est la façon dont FLIN partage une seule instance de backend entre tous les gestionnaires de requêtes. La contrainte Send + Sync rend ce patron possible au moment de la compilation.

Invariants de sécurité

La conception du trait encode plusieurs invariants de sécurité que chaque backend doit respecter :

Validation du hash. Chaque backend valide le paramètre hash avant de construire un chemin, empêchant les attaques de traversée de chemin.

Comparaison en temps constant. La vérification des URL signées utilise la comparaison d'octets en temps constant pour empêcher les attaques par timing.

Assainissement des extensions. Les extensions de fichiers sont débarrassées des séparateurs de chemin et validées contre une liste blanche de caractères.

Ce que le trait n'inclut pas

Il n'y a pas de méthodes pour lister tous les fichiers, diffuser de gros téléchargements ou gérer des listes de contrôle d'accès. Ceux-ci sont gérés par des systèmes séparés qui se composent avec le backend de stockage plutôt que de l'étendre. Cela garde le trait focalisé -- neuf méthodes, chacune avec un but clair, chacune implémentable par tout système de stockage capable de stocker et récupérer des octets par clé.


Ceci est la partie 127 de la série « Comment nous avons construit FLIN », documentant comment un CEO à Abidjan et un CTO IA ont conçu et construit un langage de programmation à partir de zéro.

Navigation de la série : - [126] Stockage de fichiers avec 4 backends - [127] Le patron de trait StorageBackend (vous êtes ici) - [128] Backends R2 et Google Cloud Storage

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude deblo

Le Step Zero ne suffisait pas : comment valider un constructeur sans valider le runtime a fait tomber toutes les sessions vocales de Déblo l’heure où nous avons livré le streaming caméra temps réel

La phase 14 a livré Déblo Eyes — streaming caméra temps réel via LiveKit vers Gemini Live native audio. Le premier deploy a fait tomber toutes les sessions vocales en production en quatre-vingt-dix secondes parce que notre Step 0 avait validé le constructeur sans exercer le runtime. Le build log de comment Déblo a eu des yeux, ce qu’un pré-vol incomplet a coûté, et quels points de polish ont été livrés ou reportés.

33 min May 20, 2026
debloclaude-opus-4.7claude-codegemini-live +25
Thales & Claude deblo

Le tiret cadratin qui a tué la production : comment un slogan marketing dans un header HTTP a fait tomber le chat de Déblo pendant 24 heures

Deux jours avant la soumission App Store, tout le produit chat de Déblo s’est cassé silencieusement. Pas de spinner, pas de toast, aucune erreur dans l’UI — juste un silence radio. L’incident de 24 heures se résumait à un seul « é » dans la valeur d’un header HTTP qui levait une UnicodeEncodeError avant qu’aucune requête vers OpenRouter ne quitte le backend. Post-mortem d’une fausse hypothèse, d’une trace Sentry, et d’un fix de six lignes qui a débloqué le lancement.

30 min May 19, 2026
debloclaude-opus-4.7claude-codeincident +19
Thales & Claude deblo

Six heures, d’une page blanche à la review Apple — Comment nous avons soumis Déblo à l’App Store, en direct

Marche à marche en direct de la soumission de Déblo à l’App Store iOS en six heures : ce que les validateurs d’Apple ont rejeté (un superscript Unicode), ce que nous avons corrigé (un Promotional Text gaspillé sur des marques tierces), et les rouages de l’ASO iOS que presque tout le monde rate.

30 min May 13, 2026
debloclaude-opus-4.7claude-codeapp-store +16