אחסון עם ביצועים גבוהים לאפליקציה: Storage Foundation API

תומאס סטיינר
תומאס סטיינר

פלטפורמת האינטרנט מציעה למפתחים יותר ויותר את הכלים הדרושים להם לבניית אפליקציות עם ביצועים משופרים לאינטרנט. הדבר הבולט ביותר הוא ש-WebAssembly (Wasm) פתח את הדלת לאפליקציות אינטרנט מהירות ועוצמתיות, בעוד שטכנולוגיות כמו Emscripten מאפשרות עכשיו למפתחים לעשות שימוש חוזר בקודים שנבדקו באינטרנט. כדי למנף את הפוטנציאל הזה בצורה אמיתית, המפתחים צריכים להיות עם אותו כוח וגמישות בכל הנוגע לאחסון.

כאן נכנס לתמונה ה-Storage Foundation API. ה-Storage Foundation API הוא ממשק API חדש ומהיר לאחסון, שפותח תרחישים לדוגמה חדשים ומבוקשים במיוחד באינטרנט, כמו הטמעה של מסדי נתונים עם ביצועים טובים וניהול חינני של קבצים זמניים גדולים. הממשק החדש מאפשר למפתחים "לתת אחסון משלהם" לאינטרנט, וכך לצמצם את פער התכונות בין קוד ספציפי לפלטפורמה.

ה-Storage Foundation API תוכנן כך שדומה למערכת קבצים בסיסית מאוד, כך שהוא מעניק למפתחים גמישות באמצעות פרימיטיבים כלליים, פשוטים וביצועים טובים שאפשר ליצור באמצעותם רכיבים ברמה גבוהה יותר. אפליקציות יכולות לנצל את הכלי המתאים ביותר לצרכים שלהן ולמצוא את האיזון הנכון בין נוחות השימוש, ביצועים ואמינות.

למה האינטרנט זקוק לממשק API נוסף לאחסון?

פלטפורמת האינטרנט מציעה למפתחים כמה אפשרויות אחסון, שכל אחת מהן מיועדת למקרים ספציפיים.

  • בבירור חלק מהאפשרויות האלה לא חופפות להצעה הזו, כי הן מאפשרות אחסון של כמויות קטנות מאוד של נתונים, כמו קובצי cookie או Web Storage API שמכילים את המנגנוני sessionStorage ואת localStorage.
  • אפשרויות אחרות כבר הוצאו משימוש מסיבות שונות, כמו File and Directory Channels API או WebSQL.
  • ל-File System Access API יש משטח API דומה, אבל השימוש בו הוא ממשק לממשק הקבצים של הלקוח ולספק גישה לנתונים שלא נמצאים בבעלות המקור או אפילו בבעלות הדפדפן. ההתמקדות האחרת נובעת משיקולי אבטחה מחמירים יותר ועלויות ביצועים גבוהות יותר.
  • אפשר להשתמש ב-IndexedDB API כקצה עורפי לחלק מתרחישי השימוש של Storage Foundation API. לדוגמה, ב-Emscripten נכללים IDBFS, מערכת קבצים קבועה שמבוססת על IndexedDB. עם זאת, מכיוון ש-IndexedDB היא במהותה מאגר ערך מפתח, יש לה מגבלות ביצועים משמעותיות. בנוסף, גישה ישירה לקטעי משנה בקובץ היא קשה עוד יותר ואיטית יותר ב-IndexedDB.
  • לבסוף, יש תמיכה רחבה בממשק CacheStorage והוא מכוון לאחסון נתונים בגודל גדול כמו משאבים של אפליקציות אינטרנט, אבל אי אפשר לשנות את הערכים.

השימוש ב-Storage Foundation API הוא ניסיון לסגור את כל הפערים באפשרויות האחסון הקודמות, באמצעות מתן הרשאה לאחסון של קבצים גדולים שניתן לשנות, שמוגדרים במקור של האפליקציה.

תרחישים לדוגמה ל-Storage Foundation API

דוגמאות לאתרים שעשויים להשתמש ב-API הזה:

  • אפליקציות לפרודוקטיביות או ליצירתיות שפועלות על כמויות גדולות של נתוני וידאו, אודיו או תמונות. אפליקציות כאלה יכולות להעביר פלחים לדיסק במקום לאחסן אותם בזיכרון.
  • אפליקציות שמסתמכות על מערכת קבצים קבועה שנגישה מ-Wasm וזקוקות לביצועים ברמה גבוהה יותר ממה ש-IDBFS יכול להבטיח.

מה זה Storage Foundation API?

ה-API כולל שני חלקים עיקריים:

  • קריאות למערכת קבצים, שמספקות פונקציונליות בסיסית לאינטראקציה עם קבצים ונתיבי קבצים.
  • נקודות אחיזה לקובץ, שמעניקות גישת קריאה וכתיבה לקובץ קיים.

קריאות למערכת קבצים

ב-Storage Foundation API מוצג אובייקט חדש בשם 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();

הדגמה (דמו)

אתם יכולים לנסות את ההדגמה של Storage Foundation API בהטמעה שמופיעה למטה. תוכלו ליצור קבצים, לשנות את השם שלהם, לכתוב בהם ולקרוא מהם, ולראות את הקיבולת הזמינה שביקשתם לעדכן בזמן ביצוע השינויים. תוכלו למצוא את קוד המקור של ההדגמה ב-Glitch.

אבטחה והרשאות

צוות Chromium תכנן והטמיע את ה-Storage Foundation API באמצעות עקרונות הליבה שמוגדרים במאמר Controling Access to Power Platform features (שליטה בגישה לתכונות חזקות של פלטפורמת האינטרנט), כולל שליטה על המשתמשים, שקיפות וארגונומיה.

בהתאם לאותה דפוס כמו ממשקי API מודרניים אחרים לאחסון באינטרנט, הגישה ל-Storage Foundation תהיה מוגבלת למקור. כלומר, למקור יש גישה רק לנתונים שנוצרו באופן עצמאי. היא מוגבלת גם בהקשרים מאובטחים.

שליטת המשתמשים

מכסת האחסון תשמש לחלוקת הגישה לשטח הדיסק ולמניעת ניצול לרעה. קודם צריך לבקש נתונים מהזיכרון שרוצים להוסיף. בדומה לממשקי API אחרים לאחסון, המשתמשים יכולים לפנות את נפח האחסון שמשתמשים תופסים ב-Storage Foundation API דרך הדפדפן.

קישורים שימושיים

אישורים

עמנואל קריבוי וריצ'ארד סטוץ סיפקו את ה-Storage Foundation API. המאמר הזה נבדק על ידי Pete LePage ו-Joe Medley.

תמונה ראשית (Hero) שנמצאת דרך Markus Spiske ב-UnFlood.