פלטפורמת האינטרנט מציעה למפתחים יותר ויותר כלים לבניית אפליקציות לאינטרנט עם ביצועים גבוהים. הטכנולוגיה הבולטת ביותר היא 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 כקצה עורפי (backend) לחלק מתרחישי השימוש של 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()
: מחזירה הבטחה שמושלמת עם הקיבולת שזמינה בהקשר הביצוע הנוכחי.
רכיבי handler של קבצים
העבודה עם קבצים מתבצעת באמצעות הפונקציות הבאות:
-
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();
אבטחה והרשאות
צוות Chromium תכנן והטמיע את Storage Foundation API על סמך עקרונות הליבה שמוגדרים במאמר שליטה בגישה לתכונות מתקדמות של פלטפורמת האינטרנט, כולל שליטת משתמשים, שקיפות וארגונומיה.
בדומה ל-APIs אחרים של אחסון מודרני באינטרנט, הגישה ל-Storage Foundation API מוגבלת למקור, כלומר מקור יכול לגשת רק לנתונים שהוא יצר בעצמו. הוא מוגבל גם להקשרים מאובטחים.
שליטת משתמשים
מכסת האחסון תשמש לחלוקת הגישה לנפח האחסון ולמניעת ניצול לרעה. צריך קודם לשלוח בקשה להקצאת נפח אחסון. בדומה לממשקי API אחרים של אחסון, משתמשים יכולים לפנות את המקום שתופס Storage Foundation API דרך הדפדפן שלהם.
קישורים שימושיים
- הסבר לציבור
- באג במעקב ב-Chromium
- ערך ב-ChromeStatus.com
- רכיב Blink:
Blink>Storage>NativeIO
- TAG Review
- כוונה ליצור אב טיפוס
- WebKit thread
- שרשור של Mozilla
תודות
ממשק Storage Foundation API הוגדר והוטמע על ידי Emanuel Krivoy וRichard Stotz. המאמר הזה נבדק על ידי Pete LePage וJoe Medley.
תמונה ראשית (Hero) דרך Markus Spiske ב-Unsplash.