אחסון עם ביצועים גבוהים לאפליקציה: 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 credentials 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): בקשה לנפח אחסון חדש (בייטים) לשימוש של הקשר הביצוע הנוכחי. הפונקציה מחזירה הבטחה (promise) שמתקבלת עם נפח הזיכרון הנותר שזמין.
  • storageFoundation.releaseCapacity(toBeReleasedCapacity): משחררת את מספר הבייטים שצוין מההקשר הנוכחי של הביצוע, ומחזירה הבטחה (promise) שמתקבלת עם הקיבולת שנותרה.
  • storageFoundation.getRemainingCapacity(): הפונקציה מחזירה הבטחה (promise) שמתקבלת בהתאם לקיבולת שזמינה בהקשר הביצוע הנוכחי.

רכיבי handler של קבצים

העבודה עם קבצים מתבצעת באמצעות הפונקציות הבאות:

  • NativeIOFile.close(): סגירת קובץ והחזרת הבטחה (promise) שמתמלאת בסיום הפעולה.
  • NativeIOFile.flush(): סנכרון (כלומר, שטיפה) של המצב של קובץ בזיכרון עם התקן האחסון, והחזרת הבטחה (promise) שמתמלאת כשהפעולה מסתיימת.
  • NativeIOFile.getLength(): הפונקציה מחזירה הבטחה (promise) שמתקבלת עם אורך הקובץ בבייטים.
  • NativeIOFile.setLength(length): מגדירה את אורך הקובץ בבייטים ומחזירה הבטחה (promise) שמתמלאת כשהפעולה מסתיימת. אם האורך החדש קטן מהאורך הנוכחי, הבייטים יוסרו החל מסוף הקובץ. אחרת, הקובץ יתארך בבאיטים עם ערך אפס.
  • 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 בהתאם לעקרונות המרכזיים שמוגדרים במאמר בקרת הגישה לתכונות מתקדמות של פלטפורמת אינטרנט, כולל בקרת משתמשים, שקיפות וארגונומיה.

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

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

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

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

אישורים

Emanuel Krivoy ו-Richard Stotz הם אלה שציינו והטמיעו את Storage Foundation API. המאמר הזה נבדק על ידי Pete LePage ו-Joe Medley.

התמונה הראשית (Hero) דרך Markus Spiske במשחק Un לשמור.