אחסון עם ביצועים גבוהים לאפליקציה: 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 Entries 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): פותח את הקובץ עם השם שצוין, אם הוא קיים, אחרת יוצר קובץ חדש. הפונקציה מחזירה הבטחה (promise) שמתקבלת עם הקובץ שנפתח.
  • storageFoundation.delete(name): הסרת הקובץ עם השם שצוין. הפונקציה מחזירה הבטחה (promise) שמתמלאת כשהקובץ נמחק.
  • storageFoundation.rename(oldName, newName): שינוי השם של הקובץ מהשם הישן לשם החדש באופן אטומי. הפונקציה מחזירה הבטחה (promise) שמתמלאת כששם הקובץ משתנה.
  • storageFoundation.getAll(): הפונקציה מחזירה הבטחה (promise) שמתקבלת בה מערך של כל שמות הקבצים הקיימים.
  • 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.

התמונה הראשית באדיבות Markus Spiske ב-Unsplash.