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 Web hautes performances et finement réglées. 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 testé et approuvé 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à qu'intervient l'API Storage Foundation. L'API Storage Foundation est une nouvelle API de stockage rapide et sans opinion qui débloque de nouveaux cas d'utilisation très demandés pour le Web, comme l'implémentation de bases de données performantes et la gestion fluide de fichiers temporaires volumineux. Grâce à cette nouvelle interface, les développeurs peuvent "apporter leur propre stockage" au 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 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 du meilleur outil pour leurs besoins, en trouvant le bon équilibre entre convivialité, performances et fiabilité.

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

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

  • Certaines de ces options ne chevauchent clairement pas cette proposition, car elles n'autorisent le stockage que de très petites quantités de données, comme les cookies ou l'API Web Storage, qui se compose 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 être en dehors de la propriété de l'origine ou même du navigateur. Cette différence d'orientation 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 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 clé-valeur, 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 avec IndexedDB.
  • Enfin, l'interface CacheStorage est largement compatible et optimisée pour stocker des données volumineuses telles que les ressources d'applications Web, mais les valeurs sont immuables.

L'API Storage Foundation vise à 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 pouvant utiliser cette API :

  • Applications de productivité ou de créativité qui fonctionnent sur de grandes quantités de données vidéo, audio ou d'image. Ces applications peuvent décharger des 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 à celles garanties par IDBFS.

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

L'API se compose de deux parties principales :

  • Les appels au 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 descripteurs de fichier, qui permettent d'accéder 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 sur l'objet window et qui inclut un certain nombre de fonctions :

  • storageFoundation.open(name) : ouvre le fichier portant le nom indiqué s'il existe, ou crée un fichier s'il n'existe pas. 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 vers 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 quantité de capacité disponible restante.
  • storageFoundation.releaseCapacity(toBeReleasedCapacity) : libère le nombre d'octets spécifié 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.

Descripteurs de fichier

Vous pouvez utiliser les fonctions suivantes pour travailler avec des fichiers :

  • NativeIOFile.close() : ferme un fichier et renvoie une promesse qui est résolue une fois l'opération terminée.
  • 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 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 lorsque l'opération est 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 à l'offset donné via un tampon qui est le résultat du transfert du tampon donné, qui est ensuite laissé détaché. Renvoie un NativeIOReadResult avec le tampon transféré et le nombre d'octets qui ont été 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 du tampon si une erreur se produit ou si la plage de lecture s'étend au-delà de la fin du fichier. Elle est définie 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 à l'offset donné. Le tampon est transféré avant l'écriture des données et est donc laissé détaché. Renvoie un NativeIOWriteResult avec le tampon transféré et le nombre d'octets écrits. Le fichier sera é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 écrits 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 guident à travers 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();

Sécurité et autorisations

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

Suivant le même modèle que 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. Elle est également limitée aux contextes sécurisés.

Contrôle des utilisateurs

Le quota de stockage sera utilisé pour distribuer l'accès à l'espace disque et pour éviter les utilisations abusives. La mémoire que vous souhaitez occuper doit d'abord être demandée. Comme pour les autres API de stockage, les utilisateurs peuvent libérer 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 héros de Markus Spiske sur Unsplash.