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 bien ajustées pour le Web. Plus particulièrement, WebAssembly (Wasm) a ouvert la voie à des applications Web rapides et puissantes, tandis que des technologies comme Emscripten permettent désormais aux développeurs de réutiliser du code éprouvé sur le Web. Pour réellement exploiter ce potentiel, les développeurs doivent disposer de la même puissance et de la même flexibilité en termes 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 non catégorique qui donne accès à de nouveaux cas d'utilisation pour le Web très demandés, tels que l'implémentation de bases de données performantes et la gestion optimale des fichiers temporaires volumineux. Grâce à cette nouvelle interface, les développeurs peuvent "importer leur propre espace de stockage" sur le Web, réduisant ainsi 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 aux développeurs de la 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 plus adapté à leurs besoins, et trouver 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 offre aux développeurs un certain nombre d'options de stockage, chacune étant conçue pour des cas d'utilisation spécifiques.

  • Il est clair que certaines de ces options ne se chevauchent 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, telles que l'API File and Directory Entries ou WebSQL.
  • L'API File System Access possède une surface d'API similaire, mais elle sert à interagir avec le système de fichiers du client et à fournir un accès à des données qui peuvent être en dehors de l'origine, voire de la propriété du navigateur. Cet objectif différent s'accompagne de considérations de sécurité plus strictes et de coûts de performance plus élevés.
  • L'API IndexedDB peut être utilisée comme backend pour certains cas d'utilisation de l'API Storage Foundation. Par exemple, Emscripten inclut IDBFS, un système de fichiers persistants basé sur IndexedDB. Cependant, comme IndexedDB est fondamentalement un magasin de clés-valeurs, ses performances sont limitées. 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 de grande taille, telles que des ressources d'application 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 susceptibles d'utiliser cette API:

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

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

L'API se compose de deux parties principales:

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

Appels au système de fichiers

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

  • storageFoundation.open(name): ouvre le fichier portant le nom donné s'il existe et crée un fichier. Renvoie une promesse qui se résout avec le fichier ouvert.
  • storageFoundation.delete(name): supprime le fichier portant le nom donné. Renvoie une promesse qui se résout lorsque le fichier est supprimé.
  • storageFoundation.rename(oldName, newName): renomme le fichier de l'ancien nom par le 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) pour l'utilisation par le contexte d'exécution actuel. Renvoie une promesse résolue avec la capacité restante.
  • 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.

Poignées de fichiers

L'utilisation des fichiers s'effectue via les fonctions suivantes:

  • NativeIOFile.close(): ferme un fichier et renvoie une promesse qui se résout une fois l'opération terminée.
  • NativeIOFile.flush(): synchronise (vide) l'état en mémoire d'un fichier avec le périphérique de stockage et renvoie une promesse qui se résout une fois l'opération terminée.
  • 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 une fois l'opération terminée. 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 de 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é, lequel est ensuite détaché à gauche. Renvoie une valeur NativeIOReadResult avec le tampon transféré et le nombre d'octets lus.

    Un NativeIOReadResult est un objet qui se compose de deux entrées:

    • buffer: ArrayBufferView, qui est le 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 que les données ne soient écrites. Il est donc dissocié. Renvoie une valeur NativeIOWriteResult avec le tampon transféré et le nombre d'octets qui ont bien été écrits. Le fichier est étendu si la plage d'écriture dépasse sa longueur.

    Un NativeIOWriteResult est un objet qui se compose de deux entrées:

    • buffer: ArrayBufferView qui est le résultat 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 correctement écrits dans buffer. Elle 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 guident à travers les différentes étapes du cycle de vie des fichiers Storage Foundation.

Ouverture, rédaction, lecture, bouclage

// 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();
}

Ouverture, référencement, suppression

// 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émonstration

Vous pouvez jouer avec la démonstration de l'API Storage Foundation dans l'intégration ci-dessous. Créez, renommez, écrivez et lisez des fichiers, et consultez la capacité disponible pour laquelle vous avez demandé l'actualisation à mesure que vous effectuez des modifications. Vous trouverez le code source de la version de démonstration sur Glitch.

Sécurité et autorisations

L'équipe Chromium a conçu et mis en œuvre l'API Storage Foundation en suivant les principes fondamentaux définis dans la section 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.

En suivant le même schéma que les autres API de stockage modernes sur le Web, l'accès à l'API Storage Foundation est lié à l'origine. Une origine ne peut donc accéder qu'aux données créées par les utilisateurs. Il est également limité à des contextes sécurisés.

Contrôle des utilisateurs

Le quota de stockage sera utilisé pour répartir l'accès à l'espace disque et empêcher toute utilisation abusive. La mémoire que vous souhaitez occuper doit d'abord être demandée. Comme d'autres API de stockage, les utilisateurs peuvent libérer de l'espace occupé par l'API Storage Foundation via leur navigateur.

Liens utiles

Remerciements

L'API Storage Foundation a été spécifiée et mise en œuvre par Emanuel Krivoy et Richard Stotz. Cet article a été examiné par Pete LePage et Joe Medley.

Image héros via Markus Spiske sur Unsplash.