Stockage hautes performances pour votre application: API Storage Foundation

La plate-forme Web offre de plus en plus aux développeurs les outils dont ils ont besoin pour créer des applications hautes performances et affinées pour le Web. Plus particulièrement, WebAssembly (Wasm) a ouvert la voie à des applications Web rapides et puissantes, tandis que des technologies telles que Emscripten permettent désormais aux développeurs de réutiliser du code éprouvé sur le Web. Pour exploiter pleinement ce potentiel, les développeurs doivent disposer de la même puissance et de la même flexibilité en matière de stockage.

C'est là que l'API Storage Foundation entre en jeu. L'API Storage Foundation est une nouvelle API de stockage rapide et neutre qui ouvre de nouveaux cas d'utilisation très demandés pour le Web, tels que l'implémentation de bases de données performantes et la gestion élégante de grands fichiers temporaires. Avec cette nouvelle interface, les développeurs peuvent "apporter leur propre stockage" sur le Web, ce qui réduit l'écart de fonctionnalités entre le code Web et le code spécifique à la plate-forme.

L'API Storage Foundation est conçue pour ressembler à un système de fichiers très basique. Elle offre ainsi aux développeurs une flexibilité en fournissant des primitives génériques, simples et performantes sur lesquelles ils peuvent créer des composants de niveau supérieur. Les applications peuvent tirer parti de l'outil le mieux adapté à leurs besoins, en trouvant le bon équilibre entre facilité d'utilisation, performances et fiabilité.

Pourquoi le Web a-t-il besoin d'une autre API de stockage ?

La plate-forme Web propose un certain nombre d'options de stockage aux développeurs, chacune étant conçue pour des cas d'utilisation spécifiques.

  • Certaines de ces options ne se chevauchent clairement pas avec cette proposition, car elles ne permettent de stocker que de très petites quantités de données, comme les cookies ou l'API Web Storage composée des mécanismes sessionStorage et localStorage.
  • D'autres options sont déjà obsolètes pour diverses raisons, comme l'API File and Directory Entries ou WebSQL.
  • L'API File System Access présente une surface d'API similaire, mais son utilisation consiste à interagir avec le système de fichiers du client et à fournir un accès aux données qui peuvent ne pas appartenir à l'origine ou même au navigateur. Cette approche différente s'accompagne de considérations de sécurité plus strictes et de coûts de performances plus élevés.
  • L'API IndexedDB peut être utilisée comme backend pour certains des cas d'utilisation de l'API Storage Foundation. Par exemple, Emscripten inclut IDBFS, un système de fichiers persistant basé sur IndexedDB. Toutefois, comme IndexedDB est fondamentalement un magasin de clés-valeurs, il présente des limites de performances importantes. De plus, l'accès direct aux sous-sections d'un fichier est encore plus difficile et plus lent sous IndexedDB.
  • Enfin, l'interface CacheStorage est largement compatible et est optimisée pour stocker des données volumineuses telles que les ressources d'applications Web, mais les valeurs sont immuables.

L'API Storage Foundation tente de combler toutes les lacunes des options de stockage précédentes en permettant le stockage performant de fichiers volumineux modifiables définis dans l'origine de l'application.

Cas d'utilisation suggérés pour l'API Storage Foundation

Voici quelques exemples de sites qui peuvent utiliser cette API:

  • Applications de productivité ou de créativité qui fonctionnent sur de grandes quantités de données vidéo, audio ou imagées Ces applications peuvent décharger des segments sur le disque au lieu de les conserver en mémoire.
  • Applications qui reposent sur un système de fichiers persistant accessible depuis Wasm et qui ont besoin de performances supérieures à celles que l'IDBFS peut garantir.

Qu'est-ce que l'API Storage Foundation ?

L'API se compose de deux parties principales:

  • Appels du système de fichiers, qui fournissent des fonctionnalités de base pour interagir avec les fichiers et les chemins d'accès aux fichiers.
  • Handles de fichier, qui fournissent un accès en lecture et en écriture à un fichier existant.

Appels du système de fichiers

L'API Storage Foundation introduit un nouvel objet, storageFoundation, qui réside dans l'objet window et qui inclut un certain nombre de fonctions:

  • storageFoundation.open(name): ouvre le fichier avec le nom donné s'il existe, sinon crée un nouveau fichier. Renvoie une promesse qui se résout avec le fichier ouvert.
  • storageFoundation.delete(name): supprime le fichier portant le nom indiqué. Renvoie une promesse qui se résout lorsque le fichier est supprimé.
  • storageFoundation.rename(oldName, newName): renomme le fichier de l'ancien nom au nouveau nom de manière atomique. Renvoie une promesse qui se résout lorsque le fichier est renommé.
  • storageFoundation.getAll(): renvoie une promesse qui se résout avec un tableau de tous les noms de fichiers existants.
  • storageFoundation.requestCapacity(requestedCapacity): demande une nouvelle capacité (en octets) à utiliser par le contexte d'exécution actuel. Renvoie une promesse résolue avec la quantité de capacité restante disponible.
  • storageFoundation.releaseCapacity(toBeReleasedCapacity): libère le nombre d'octets spécifié à partir du contexte d'exécution actuel et renvoie une promesse qui se résout avec la capacité restante.
  • storageFoundation.getRemainingCapacity(): renvoie une promesse qui se résout avec la capacité disponible pour le contexte d'exécution actuel.

Handles de fichier

Les fonctions suivantes permettent de travailler avec des fichiers:

  • NativeIOFile.close(): ferme un fichier et renvoie une promesse qui se résout à la fin de l'opération.
  • NativeIOFile.flush(): synchronise (c'est-à-dire vide) l'état en mémoire d'un fichier avec le périphérique de stockage, et renvoie une promesse qui se résout à la fin de l'opération.
  • NativeIOFile.getLength(): renvoie une promesse qui se résout avec la longueur du fichier en octets.
  • NativeIOFile.setLength(length): définit la longueur du fichier en octets et renvoie une promesse qui se résout à la fin de l'opération. Si la nouvelle longueur est inférieure à la longueur actuelle, les octets sont supprimés à partir de la fin du fichier. Sinon, le fichier est étendu avec des octets à valeur nulle.
  • NativeIOFile.read(buffer, offset): lit le contenu du fichier au décalage donné via un tampon résultant du transfert du tampon donné, qui est ensuite laissé détaché. Renvoie un NativeIOReadResult avec le tampon transféré et le nombre d'octets lus.

    Un NativeIOReadResult est un objet composé de deux entrées:

    • buffer: ArrayBufferView, résultat du transfert du tampon transmis à read(). Il est du même type et de la même longueur que le tampon source.
    • readBytes: nombre d'octets lus dans buffer. Cette valeur peut être inférieure à la taille de la mémoire tampon si une erreur se produit ou si la plage de lecture s'étend au-delà de la fin du fichier. Il est défini sur zéro si la plage de lecture dépasse la fin du fichier.
  • NativeIOFile.write(buffer, offset): écrit le contenu du tampon donné dans le fichier au décalage donné. Le tampon est transféré avant l'écriture de données et reste donc détaché. Renvoie un NativeIOWriteResult avec le tampon transféré et le nombre d'octets écrits avec succès. Le fichier est étendu si la plage d'écriture dépasse sa longueur.

    Un NativeIOWriteResult est un objet composé de deux entrées:

    • buffer: ArrayBufferView résultant du transfert du tampon transmis à write(). Il est du même type et de la même longueur que le tampon source.
    • writtenBytes: nombre d'octets écrits avec succès dans buffer. Cette valeur peut être inférieure à la taille de la mémoire tampon en cas d'erreur.

Exemples complets

Pour clarifier les concepts présentés ci-dessus, voici deux exemples complets qui vous expliquent les différentes étapes du cycle de vie des fichiers Storage Foundation.

Ouverture, écriture, lecture, fermeture

// Open a file (creating it if needed).
const file = await storageFoundation.open('test_file');
try {
  // Request 100 bytes of capacity for this context.
  await storageFoundation.requestCapacity(100);

  const writeBuffer = new Uint8Array([64, 65, 66]);
  // Write the buffer at offset 0. After this operation, `result.buffer`
  // contains the transferred buffer and `result.writtenBytes` is 3,
  // the number of bytes written. `writeBuffer` is left detached.
  let result = await file.write(writeBuffer, 0);

  const readBuffer = new Uint8Array(3);
  // Read at offset 1. `result.buffer` contains the transferred buffer,
  // `result.readBytes` is 2, the number of bytes read. `readBuffer` is left
  // detached.
  result = await file.read(readBuffer, 1);
  // `Uint8Array(3) [65, 66, 0]`
  console.log(result.buffer);
} finally {
  file.close();
}

Ouvrir, lister, supprimer

// Open three different files (creating them if needed).
await storageFoundation.open('sunrise');
await storageFoundation.open('noon');
await storageFoundation.open('sunset');
// List all existing files.
// `["sunset", "sunrise", "noon"]`
await storageFoundation.getAll();
// Delete one of the three files.
await storageFoundation.delete('noon');
// List all remaining existing files.
// `["sunrise", "noon"]`
await storageFoundation.getAll();

Démo

Vous pouvez tester la démonstration de l'API Storage Foundation dans l'intégration ci-dessous. Créez, renommez, écrivez dans et lisez des fichiers, et consultez la capacité disponible que vous avez demandée à mettre à jour à mesure que vous apportez des modifications. Vous trouverez le code source de la démonstration sur Glitch.

Sécurité et autorisations

L'équipe Chromium a conçu et implémenté l'API Storage Foundation en suivant les principes de base définis dans Controlling Access to Powerful Web Platform Features (Contrôler l'accès aux fonctionnalités puissantes de la plate-forme Web), y compris le contrôle utilisateur, la transparence et l'ergonomie.

Comme les autres API de stockage modernes sur le Web, l'accès à l'API Storage Foundation est lié à l'origine, ce qui signifie qu'une origine ne peut accéder qu'aux données qu'elle a créées. Il est également limité aux contextes sécurisés.

Contrôle des utilisateurs

Le quota de stockage permet de distribuer l'accès à l'espace disque et d'éviter les abus. La mémoire que vous souhaitez occuper doit d'abord être demandée. Comme pour les autres API de stockage, les utilisateurs peuvent effacer l'espace occupé par l'API Storage Foundation via leur navigateur.

Liens utiles

Remerciements

L'API Storage Foundation a été spécifiée et implémentée par Emanuel Krivoy et Richard Stotz. Cet article a été relu par Pete LePage et Joe Medley.

Image Hero via Markus Spiske sur Unsplash.