आपके ऐप्लिकेशन के लिए बेहतर परफ़ॉर्मेंस वाला स्टोरेज: स्टोरेज फ़ाउंडेशन एपीआई

वेब प्लैटफ़ॉर्म, डेवलपर को वेब के लिए बेहतर परफ़ॉर्मेंस वाले ऐप्लिकेशन बनाने के लिए ज़रूरी टूल उपलब्ध कराता है. सबसे अहम बात यह है कि WebAssembly (Wasm) की मदद से, तेज़ और बेहतर वेब ऐप्लिकेशन बनाए जा सकते हैं. साथ ही, Emscripten जैसी टेक्नोलॉजी की मदद से, डेवलपर अब वेब पर पहले से टेस्ट किए गए कोड का फिर से इस्तेमाल कर सकते हैं. इस क्षमता का ज़्यादा से ज़्यादा फ़ायदा पाने के लिए, डेवलपर के पास स्टोरेज के लिए उतनी ही सुविधाएं और विकल्प होने चाहिए जितनी कि डिवाइस के लिए होती हैं.

ऐसे में, Storage Foundation API का इस्तेमाल किया जा सकता है. Storage Foundation API, स्टोरेज के लिए एक नया और तेज़ एपीआई है. यह वेब के लिए, नए और ज़्यादा अनुरोध किए गए इस्तेमाल के उदाहरणों को अनलॉक करता है. जैसे, बेहतर परफ़ॉर्मेंस वाले डेटाबेस लागू करना और बड़ी अस्थायी फ़ाइलों को आसानी से मैनेज करना. इस नए इंटरफ़ेस की मदद से, डेवलपर वेब पर "अपना स्टोरेज" जोड़ सकते हैं. इससे वेब और प्लैटफ़ॉर्म के हिसाब से कोड के बीच की सुविधाओं में अंतर कम हो जाता है.

Storage Foundation API को एक बहुत ही बुनियादी फ़ाइल सिस्टम के तौर पर डिज़ाइन किया गया है. इससे डेवलपर को सामान्य, आसान, और बेहतर परफ़ॉर्म करने वाले प्राइमिटिव मिलते हैं. इनकी मदद से, वे बेहतर लेवल के कॉम्पोनेंट बना सकते हैं. ऐप्लिकेशन अपनी ज़रूरतों के हिसाब से सबसे अच्छे टूल का फ़ायदा ले सकते हैं. इससे, इस्तेमाल करने के तरीके, परफ़ॉर्मेंस, और भरोसेमंदता के बीच सही संतुलन मिलता है.

वेब को स्टोरेज के लिए किसी दूसरे एपीआई की ज़रूरत क्यों है?

वेब प्लैटफ़ॉर्म, डेवलपर के लिए स्टोरेज के कई विकल्प उपलब्ध कराता है. इनमें से हर विकल्प को, इस्तेमाल के खास उदाहरणों को ध्यान में रखकर बनाया गया है.

  • इनमें से कुछ विकल्प, इस प्रस्ताव से मेल नहीं खाते. ऐसा इसलिए है, क्योंकि इनमें बहुत कम डेटा सेव किया जा सकता है. जैसे, कुकी या sessionStorage और localStorage मेकेनिज्म वाले वेब स्टोरेज एपीआई.
  • फ़ाइल और डायरेक्ट्री एंट्री एपीआई या WebSQL जैसे अन्य विकल्पों को कई वजहों से पहले ही बंद कर दिया गया है.
  • File System Access API का एपीआई, FileSystem API से मिलता-जुलता है. हालांकि, इसका इस्तेमाल क्लाइंट के फ़ाइल सिस्टम के साथ इंटरफ़ेस करने और ऐसे डेटा का ऐक्सेस देने के लिए किया जाता है जो ऑरिजिन या ब्राउज़र के मालिकाना हक से बाहर हो सकता है. इस अलग फ़ोकस के साथ, सुरक्षा से जुड़ी ज़्यादा सख्त शर्तें और परफ़ॉर्मेंस की ज़्यादा लागत आती है.
  • IndexedDB API का इस्तेमाल, Storage Foundation API के कुछ इस्तेमाल के उदाहरणों के लिए बैकएंड के तौर पर किया जा सकता है. उदाहरण के लिए, Emscripten में IDBFS शामिल है, जो IndexedDB पर आधारित, हमेशा मौजूद रहने वाला फ़ाइल सिस्टम है. हालांकि, IndexedDB मूल रूप से एक की-वैल्यू स्टोर है. इसलिए, इसकी परफ़ॉर्मेंस पर काफ़ी सीमाएं हैं. इसके अलावा, IndexedDB में किसी फ़ाइल के सबसे छोटे हिस्सों को सीधे ऐक्सेस करना और भी मुश्किल और धीमा होता है.
  • आखिर में, CacheStorage इंटरफ़ेस का इस्तेमाल, कई प्लैटफ़ॉर्म पर किया जा सकता है. साथ ही, इसे वेब ऐप्लिकेशन के संसाधनों जैसे बड़े डेटा को स्टोर करने के लिए ट्यून किया गया है. हालांकि, इसकी वैल्यू में बदलाव नहीं किया जा सकता.

Storage Foundation API, स्टोरेज के पिछले विकल्पों के सभी अंतर को खत्म करने की कोशिश है. इससे, ऐप्लिकेशन के ऑरिजिन में तय की गई बड़ी फ़ाइलों को बेहतर तरीके से स्टोर किया जा सकता है.

Storage Foundation API के इस्तेमाल के सुझाए गए उदाहरण

इस एपीआई का इस्तेमाल करने वाली साइटों के उदाहरणों में ये शामिल हैं:

  • ऐसे ऐप्लिकेशन जो ज़्यादा वीडियो, ऑडियो या इमेज डेटा पर काम करते हैं. ऐसे ऐप्लिकेशन, सेगमेंट को मेमोरी में सेव करने के बजाय, डिस्क पर ऑफ़लोड कर सकते हैं.
  • ऐसे ऐप्लिकेशन जो Wasm से ऐक्सेस किए जा सकने वाले, हमेशा मौजूद फ़ाइल सिस्टम पर निर्भर करते हैं. साथ ही, उन्हें IDBFS से मिलने वाली परफ़ॉर्मेंस से ज़्यादा परफ़ॉर्मेंस की ज़रूरत होती है.

Storage Foundation 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 को डिज़ाइन और लागू किया है. इन सिद्धांतों में, उपयोगकर्ता कंट्रोल, पारदर्शिता, और काम करने के तरीके शामिल हैं.

वेब पर मौजूद अन्य आधुनिक स्टोरेज एपीआई की तरह ही, Storage Foundation एपीआई का ऐक्सेस, ऑरिजिन के हिसाब से तय होता है. इसका मतलब है कि कोई ऑरिजिन सिर्फ़ अपना बनाया हुआ डेटा ऐक्सेस कर सकता है. यह सुविधा, सुरक्षित कॉन्टेक्स्ट तक ही सीमित है.

उपयोगकर्ता के कंट्रोल की जानकारी

स्टोरेज कोटे का इस्तेमाल, डिस्क स्पेस का ऐक्सेस देने और उसका गलत इस्तेमाल रोकने के लिए किया जाएगा. आपको जिस स्टोरेज का इस्तेमाल करना है उसके लिए, पहले अनुरोध करना होगा. अन्य स्टोरेज एपीआई की तरह ही, उपयोगकर्ता अपने ब्राउज़र से, Storage Foundation API के लिए इस्तेमाल किया गया स्टोरेज खाली कर सकते हैं.

काम के लिंक

Acknowledgements

Storage Foundation API को एमानुएल क्रिवॉय और रिचर्ड स्टोट्ज़ ने तय और लागू किया था. इस लेख की समीक्षा पीट लेपेज और जो मेडली ने की है.

Unsplash पर Markus Spiske की दी गई हीरो इमेज.