Высокопроизводительное хранилище для вашего приложения: API Storage Foundation

Веб-платформа все чаще предлагает разработчикам инструменты, необходимые для создания отлаженных высокопроизводительных приложений для веба. В частности, WebAssembly (Wasm) открыла дверь быстрым и мощным веб-приложениям, а такие технологии, как Emscripten, теперь позволяют разработчикам повторно использовать проверенный и испытанный код в вебе. Чтобы по-настоящему использовать этот потенциал, разработчики должны иметь такую ​​же мощность и гибкость, когда дело касается хранения.

Вот тут-то и появляется Storage Foundation API. Storage Foundation API — это новый быстрый и непредвзятый API хранилища, который открывает новые и востребованные варианты использования для веба, такие как реализация производительных баз данных и изящное управление большими временными файлами. С этим новым интерфейсом разработчики могут «принести свое собственное хранилище» в веб, сокращая разрыв между веб- и платформенно-специфичным кодом.

Storage Foundation API разработан так, чтобы напоминать очень простую файловую систему, поэтому он дает разработчикам гибкость, предоставляя общие, простые и производительные примитивы, на которых они могут создавать компоненты более высокого уровня. Приложения могут использовать лучший инструмент для своих нужд, находя правильный баланс между удобством использования, производительностью и надежностью.

Зачем Интернету нужен еще один API для хранения данных?

Веб-платформа предлагает разработчикам ряд вариантов хранения данных, каждый из которых создан с учетом конкретных вариантов использования.

  • Некоторые из этих вариантов явно не пересекаются с этим предложением, поскольку они позволяют хранить только очень небольшие объемы данных, например, файлы cookie или API веб-хранилища, состоящий из механизмов sessionStorage и localStorage .
  • Другие варианты уже устарели по разным причинам, например API файлов и записей каталогов или WebSQL .
  • API доступа к файловой системе имеет похожую поверхность API, но его использование заключается в интерфейсе с файловой системой клиента и предоставлении доступа к данным, которые могут находиться вне собственности источника или даже браузера. Этот другой фокус сопровождается более строгими соображениями безопасности и более высокими затратами на производительность.
  • IndexedDB API можно использовать в качестве бэкэнда для некоторых вариантов использования Storage Foundation API. Например, Emscripten включает IDBFS , постоянную файловую систему на основе IndexedDB. Однако, поскольку IndexedDB по сути является хранилищем ключ-значение, он имеет существенные ограничения производительности. Более того, прямой доступ к подразделам файла в IndexedDB еще сложнее и медленнее.
  • Наконец, интерфейс CacheStorage широко поддерживается и настроен для хранения больших объемов данных, таких как ресурсы веб-приложений, но значения являются неизменяемыми.

Storage Foundation API — это попытка закрыть все пробелы предыдущих вариантов хранения, обеспечив эффективное хранение изменяемых больших файлов, определенных в источнике приложения.

Предлагаемые варианты использования API Storage Foundation

Примеры сайтов, которые могут использовать этот API:

  • Приложения для производительности или творчества, которые работают с большими объемами видео, аудио или изображений. Такие приложения могут выгружать сегменты на диск вместо того, чтобы хранить их в памяти.
  • Приложения, использующие постоянную файловую систему, доступную из Wasm, и которым требуется большая производительность, чем может гарантировать IDBFS.

Что такое API Storage Foundation?

API состоит из двух основных частей:

  • Вызовы файловой системы , которые обеспечивают базовую функциональность для взаимодействия с файлами и путями к файлам.
  • Дескрипторы файлов , которые обеспечивают доступ на чтение и запись к существующему файлу.

Вызовы файловой системы

API Storage Foundation представляет новый объект storageFoundation , который находится в объекте window и включает в себя ряд функций:

  • storageFoundation.open(name) : открывает файл с указанным именем, если он существует, в противном случае создает новый файл. Возвращает обещание, которое разрешается с открытым файлом.
  • storageFoundation.delete(name) : Удаляет файл с указанным именем. Возвращает обещание, которое разрешается при удалении файла.
  • storageFoundation.rename(oldName, newName) : Переименовывает файл со старого имени на новое имя атомарно. Возвращает обещание, которое разрешается при переименовании файла.
  • storageFoundation.getAll() : возвращает обещание, которое разрешается с помощью массива всех существующих имен файлов.
  • storageFoundation.requestCapacity(requestedCapacity) : запрашивает новую емкость (в байтах) для использования текущим контекстом выполнения. Возвращает обещание, которое было разрешено с оставшимся объемом доступной емкости.
  • storageFoundation.releaseCapacity(toBeReleasedCapacity) : освобождает указанное количество байтов из текущего контекста выполнения и возвращает обещание, которое разрешается с оставшейся емкостью.
  • storageFoundation.getRemainingCapacity() : возвращает обещание, которое разрешается с доступной емкостью для текущего контекста выполнения.

Файловые дескрипторы

Работа с файлами происходит с помощью следующих функций:

  • NativeIOFile.close() : закрывает файл и возвращает обещание, которое разрешается после завершения операции.
  • NativeIOFile.flush() : синхронизирует (то есть очищает) состояние файла в памяти с устройством хранения и возвращает обещание, которое разрешается после завершения операции.
  • NativeIOFile.getLength() : возвращает обещание, которое разрешается с длиной файла в байтах.
  • NativeIOFile.setLength(length) : Устанавливает длину файла в байтах и ​​возвращает обещание, которое разрешается после завершения операции. Если новая длина меньше текущей, байты удаляются, начиная с конца файла. В противном случае файл расширяется байтами с нулевым значением.
  • NativeIOFile.read(buffer, offset) : Считывает содержимое файла по указанному смещению через буфер, который является результатом передачи указанного буфера, который затем остается отсоединенным. Возвращает NativeIOReadResult с переданным буфером и количеством байтов, которые были успешно прочитаны.

    NativeIOReadResult — это объект, состоящий из двух записей:

    • buffer : ArrayBufferView , который является результатом передачи буфера, переданного в read() . Он имеет тот же тип и длину, что и исходный буфер.
    • readBytes : Количество байтов, которые были успешно считаны в buffer . Может быть меньше размера буфера, если произошла ошибка или если диапазон чтения выходит за пределы конца файла. Устанавливается в ноль, если диапазон чтения выходит за пределы конца файла.
  • NativeIOFile.write(buffer, offset) : записывает содержимое указанного буфера в файл с указанным смещением. Буфер передается до записи любых данных и поэтому остается отсоединенным. Возвращает NativeIOWriteResult с переданным буфером и количеством успешно записанных байтов. Файл будет расширен, если диапазон записи превысит его длину.

    NativeIOWriteResult — это объект, состоящий из двух записей:

    • buffer : ArrayBufferView , который является результатом передачи буфера, переданного write() . Он имеет тот же тип и длину, что и исходный буфер.
    • writtenBytes : Количество байтов, которые были успешно записаны в buffer . Может быть меньше размера буфера, если произошла ошибка.

Полные примеры

Чтобы сделать представленные выше концепции более понятными, приведем два полных примера, которые проведут вас по различным этапам жизненного цикла файлов Storage Foundation.

Открытие, письмо, чтение, закрытие

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

Открытие, листинг, удаление

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

Демо

Вы можете поиграть с демо-версией API Storage Foundation в представленном ниже примере. Создавайте, переименовывайте, записывайте и читайте файлы, а также смотрите доступную емкость, которую вы запросили, обновляйте по мере внесения изменений. Исходный код демо-версии можно найти на Glitch.

Безопасность и разрешения

Команда Chromium разработала и реализовала API Storage Foundation, используя основные принципы, определенные в документе «Управление доступом к мощным функциям веб-платформы» , включая пользовательский контроль, прозрачность и эргономичность.

Следуя той же схеме, что и другие современные API-интерфейсы хранения в Интернете, доступ к API Storage Foundation привязан к источнику, что означает, что источник может получать доступ только к самостоятельно созданным данным. Он также ограничен безопасными контекстами.

Пользовательский контроль

Квота хранилища будет использоваться для распределения доступа к дисковому пространству и предотвращения злоупотреблений. Память, которую вы хотите занять, должна быть сначала запрошена. Как и другие API хранилища, пользователи могут очистить пространство, занимаемое API Storage Foundation, через свой браузер.

Полезные ссылки

Благодарности

Storage Foundation API был разработан и реализован Эмануэлем Кривой и Ричардом Стотцем . Рецензентами этой статьи выступили Пит ЛеПейдж и Джо Медли .

Изображение героя предоставлено Маркусом Списке на Unsplash .