• कुछ साल पहले तक रीयल-टाइम मल्टीप्लेयर डेटा सिंकिंग सबसे कठिन समस्याओं में से एक थी, जिसके लिए विशेषज्ञ लोगों और कंपनी-स्तर के निवेश की ज़रूरत पड़ती थी, लेकिन अब सिर्फ npm install एक बार चलाकर हॉबी प्रोजेक्ट में भी मल्टीप्लेयर UI बनाया जा सकता है
  • Automerge लोकल-फर्स्ट, मल्टीप्लेयर-सेफ और वर्ज़न-मैनेजमेंट-सक्षम डेटा मॉडल बनाने का टूल है, जो React के useState पैटर्न जैसे तरीके से डेटा persistence, हिस्ट्री मैनेजमेंट, collaborators को broadcast, और conflict resolution को अपने-आप संभाल लेता है, बिना UI को इसकी चिंता किए
  • ब्राउज़र-आधारित मल्टीप्लेयर ऑडियो एडिटर Ducking के उदाहरण में, डेटा मॉडल को इस तरह डिज़ाइन करना कि वह CRDT operations से स्वाभाविक रूप से मैप हो सके, सबसे अहम बात है
  • लिस्ट reordering जैसी स्थितियों में, जहाँ Automerge गारंटी नहीं देता, वहाँ application layer code में खुद अधिक मज़बूत invariants लागू करने पड़ते हैं
  • मूल महत्व यह है कि जो रीयल-टाइम collaborative editing कभी इंडस्ट्रियल-ग्रेड जादू जैसी चीज़ थी, वह अब कुछ लोगों के छोटे ऐप्स में भी खुलकर लागू की जा सकती है

पृष्ठभूमि — Ducking प्रोजेक्ट

  • पिछले कुछ महीनों में पार्टनर के पॉडकास्ट के लिए ब्राउज़र-आधारित मल्टीप्लेयर ऑडियो एडिटर Ducking बनाया गया
  • यह अजीब लगा कि ऑडियो एडिटिंग अब भी 20 साल पुराने single-user desktop apps और फ़ाइलों के आदान-प्रदान वाले तरीके पर टिकी हुई है
    • ज़रूरत ऐसे Google Docs या Figma जैसे collaborative workflow की थी, जहाँ एक व्यक्ति clips एडिट करे और दूसरा transcript ठीक करे या EQ settings बदले
    • साथ ही comments, history, और change tracking जैसे आधुनिक collaboration tools भी चाहिए थे
  • पिछले लेख में बताई गई अनोखी UI design और audio layout model ने single editor को बेहतर बनाया, लेकिन असली चाहत थी और अधिक collaborative workflow

Automerge कैसे काम करता है

  • ऑडियो blob को छोड़कर Ducking का सारा डेटा Automerge document में स्टोर होता है
  • मुख्य पैटर्न React डेवलपर्स के लिए परिचित है: hook से डेटा लाओ, render करो, और async change request dispatch करो; डेटा बदलने के बाद hook rerender trigger कर देता है
    • useDocument hook का उदाहरण: const [doc, changeDoc] = useDocument<Episode>(docUrl) के रूप में document लिया जाता है, और input बदलने पर changeDoc((d) => { d.title = e.target.value }) से update किया जाता है
  • डेटा update operations दिखने में imperative लगते हैं, लेकिन वे native JS objects और arrays से अलग हैं
    • इनमें methods कम होते हैं, ये तुरंत mutate नहीं करते, बल्कि internally mutation को intercept करके उसे document history की changelist entries में बदल देते हैं
  • Automerge साधारण उपयोगों में बहुत कुछ संभाल लेता है, लेकिन यह जादू नहीं है; इसके invariants हमेशा इच्छित अर्थ से मेल नहीं खाते, इसलिए सावधानी से डेटा मॉडल डिज़ाइन करना ज़रूरी है
    • कोशिश यह रहती है कि अधिकतर अर्थपूर्ण user actions, Automerge द्वारा दिए गए single operation से मेल खाएँ
    • संबंधित डेटा पर अलग-अलग user actions, उस Automerge operation के invariants के नज़रिए से स्वाभाविक रूप से resolve हों
    • स्टोर किए जाने वाले canonical data और calculation से निकाले गए derived data को साफ़-साफ़ अलग रखा जाए

मल्टीप्लेयर के लिए डेटा मॉडलिंग

  • Ducking के डेटा मॉडल में clip एक ऐसी window है जो immutable base audio source के किसी हिस्से को प्ले करती है; यह playback range, effect application और timeline space occupancy संभालती है
    • सबसे आम effect यह है कि clip, base audio की volume को समय के साथ बदलता है ताकि crossfade हो सके या noise हटाई जा सके
  • शुरुआत में हर clip के पास clip start के आधार पर time-indexed volume levels की सूची थी, लेकिन समस्या यह थी कि ज़्यादातर volume changes clip नहीं बल्कि base audio से संबंधित थे
    • अगर clip start time थोड़ा आगे-पीछे कर दिया जाए तो सारे volume changes ऑडियो के किसी और हिस्से पर लागू होने लगते थे
    • clip start बदलने पर सारे volume timestamps अपडेट करने वाला code लिखना खराब विकल्प था
  • अगर दो collaborators एक साथ clip start time एडिट करें, तो हर edit में start time और सभी volume automation timestamps के updates साथ बंध जाते
    • Automerge को इन changes के बीच का causal relationship पता नहीं होता, इसलिए merge के समय वे उलझे हुए तरीके से resolve हो सकते थे
    • यह उस आम समस्या का उदाहरण है जहाँ एक अर्थपूर्ण action कई persisted data points को ऐसे causal तरीके से अपडेट करना चाहता है जिसे CRDT समझ नहीं पाता
  • समाधान यह था कि audio effect data को clip से हटाकर base audio के timeframe के आधार पर migrate किया जाए
    • इससे clip start या length बदलने पर update की ज़रूरत नहीं रही, और कई editors यदि start time, volume automation या दूसरे effects बदलें भी तो वे एक-दूसरे से स्वतंत्र रहकर सही merge होने की संभावना बढ़ाते हैं
  • single-user UI और multiplayer UI के बीच फ़र्क
    • single-user UI में अक्सर पुराने डेटा मॉडल को रखकर write time पर extra calculation जोड़ दी जाती है
    • multiplayer UI में सभी persisted data को orthogonal state में रखने के लिए डेटा मॉडल migration कहीं ज़्यादा आम हो जाती है
  • इसका नतीजा यह हुआ कि write time simplification और read time calculation को मज़बूती से प्राथमिकता दी गई, ताकि Automerge की automatic merging का अधिकतम लाभ मिल सके
  • डेटा shape migration पर सलाह
    • यह स्वीकार करें कि build process के दौरान डेटा shapes migrate करनी पड़ेंगी, और पहली बड़ी migration से न डरें—शुरुआत में थोड़ा समय देकर इसकी practice कर लें
    • client-side read-time handling, server-side bulk upgrades जैसी कई patterns मौजूद हैं
    • migration से पहले और बाद में समानता जाँचने के लिए कोई सुविधाजनक invariant मिल जाए तो काम बहुत आसान हो जाता है
    • Ducking में migration से पहले और बाद में हर project का audio export करके audio fingerprint से जाँचा गया कि कुछ बदला तो नहीं; इससे बड़े schema changes भी बिना डर deploy किए जा सके

लिस्ट reordering लागू करना

  • कभी-कभी Automerge जिन guarantees को नहीं देता, उनके लिए application layer code में खुद ज़्यादा सख्त invariants लिखने पड़ते हैं
  • Ducking की magnetic timeline (चलाए जाने वाले clips की sorted list) बनाते समय यही समस्या आई
    • Automerge arrays में index के आधार पर item delete और insert करने की operations देता है, लेकिन किसी मौजूदा item को atomic re-order करने की operation नहीं देता
  • इसके लिए ज्ञात समाधान मौजूद हैं
    • Martin Kleppmann ने atomic list reordering operations पर paper प्रकाशित किया
    • Liangrun Da के साथ मिलकर "Extending JSON CRDTs with Move Operations" नाम का paper भी प्रकाशित किया गया
    • इसे Automerge में जोड़ने के लिए एक draft PR भी है, लेकिन वह अभी merge नहीं हुई है
  • साधारण reordering तरीके की समस्या
    • मौजूदा index से object delete करके उसे destination index पर फिर से add करना
    • इन दो operations के invariants को जोड़ने पर भी वांछित invariant—"बहुत से concurrent reorders होने पर object list में ठीक एक बार मौजूद रहे"—गारंटी नहीं होता
    • अगर कई concurrent delete+insert हों, तो object list में कई जगह आ सकता है (अगर Alice और Bob दोनों B को delete+insert से move करें, तो दोनों deletes एक tombstone में merge हो जाएँगे, लेकिन दोनों inserts अलग नए elements बनाएँगे, और दोनों बच जाएँगे, इसलिए B दो बार दिखाई देगा)
  • application layer में "ठीक एक बार" invariant की सीधी implementation
    • जब कोई clip timeline में insert होता है, तो उसे एक semantic id दिया जाता है
    • reorder करते समय ऊपर बताए अनुसार delete+insert operations trigger किए जाते हैं
    • read time पर application उसी semantic id के duplicates scan करती है, delete न हुए पहले item को मनमाने ढंग से चुनती है और बाकी को ignore कर देती है
    • इससे object list में एक ही बार रहता है और सभी readers हमेशा एक जैसे final state पर पहुँचते हैं
  • Ducking में list reordering ही एकमात्र operation था जो Automerge सीधे नहीं देता था; PR merge हो जाने पर application-level logic की ज़रूरत शायद नहीं रहेगी

document history

  • अच्छे multiplayer UI को history management tools चाहिए होते हैं, ताकि collaborators अपनी अनुपस्थिति में हुए changes देख सकें, diff पर comments कर सकें, और पुराने versions compare या rollback कर सकें
  • Automerge document version history track करता है और history तथा comparison के लिए बेहतरीन primitives देता है
    • हालाँकि उस जानकारी को कैसे दिखाना है और कौन-से concepts users के सामने रखने हैं, यह application developer तय करता है
  • Ink & Switch के Patchwork lab notes की सिफारिश की गई
    • users के सामने branches expose करने और universal comments पर किया गया काम खास तौर पर दिलचस्प है
  • Ducking ने अपेक्षाकृत सरल collaboration और history model अपनाया
    • user-defined names वाले checkpoint सहित linear version history, जहाँ checkpoint changes को group करने, discussion, diff और rollback की इकाई के रूप में काम करता है
    • audio के किसी खास point, transcript के किसी region, या version checkpoint से जुड़े comment thread
  • अभी तक branches लाने की पर्याप्त ज़रूरत नहीं पड़ी, लेकिन आगे यह उपयोगी हो सकता है

टेक्स्ट और marks

  • rich text पर काम करना खास तौर पर कठिन होता है, जब editable text के ऊपर custom logic रखनी हो
    • rich text और multiplayer software की व्यापक चुनौतियों को समझाने वाला Peritext paper सुझाया गया
  • Automerge का rich text schema marks को शामिल करता है—ऐसी annotations जो text ranges पर लागू होती हैं और text edit होने पर भी सुसंगत रहती हैं
    • आम तौर पर इनका उपयोग bold या italic formatting के लिए होता है, लेकिन application-specific custom marks भी बनाए जा सकते हैं
  • Ducking में custom marks के दो उपयोग
    • transcript के उस region को track करना जो किसी comment thread का target है
    • transcript के शब्दों के timestamps track करना, जबकि editing की अनुमति बनी रहे
      • transcription service transcript को ऐसे richtext object के रूप में Automerge में स्टोर करती है जिसमें हर शब्द पर timing info mark लगा होता है
      • अगर किसी छोटे typo के कारण सिर्फ एक शब्द बदला जाए तो mark बना रहता है और सारी timing info बची रहती है
      • अगर पूरा वाक्य बदला जाए, तो बीच के कुछ marks हट सकते हैं, लेकिन वाक्य की शुरुआत और अंत के marks बने रहते हैं, जिससे कम से कम मोटा timing info मिल जाता है
  • marks की एक सीमा यह है कि उनका datum simple value होना चाहिए (आमतौर पर string), और वह multiplayer merge नहीं होता
    • transcript timing info जैसे छोटे और immutable data के लिए JSON को string के रूप में serialize किया जाता है
    • comment thread जैसे अधिक जटिल या mutable data के लिए mark में सिर्फ id रखी जाती है और असली data document में कहीं और स्टोर किया जाता है
  • marks, multiplayer rich text के ऊपर application features बनाने के लिए शानदार आधार देते हैं

अगला लेख — सीरीज़ की रूपरेखा

  • यह लेख Ducking बनाने पर आधारित 3-भागों की श्रृंखला का दूसरा भाग है
    • भाग 1: software की अनोखी UI design की व्याख्या
    • भाग 2 (यह लेख): Automerge पर नज़र डालने की सिफारिश और हॉबी multiplayer projects बनाने की संभावना
    • अंतिम भाग 3: Ducking बनाने के अनुभव पर पुनरावलोकन
  • अंतिम भाग 3 के बारे में उल्लेख
    • LLM support का उपयोग काम की productivity बढ़ाने के बजाय अधिक sketching और hammock time निकालने के लिए किया गया
    • सिर्फ कुछ लोगों को संतुष्ट करने वाले narrowcast software बनाने की खुशी

संभावित सवाल

ऑडियो डेटा का क्या?

  • सारा multiplayer data Automerge में स्टोर होता है, लेकिन base audio blob को तेज playback के लिए Automerge में नहीं रखा जाता; उसका अलग प्रबंधन चाहिए
  • लक्ष्य यह है कि नया collaborator page load होने के 4 सेकंड के भीतर सुनना और एडिट करना शुरू कर सके—यह desktop app launch करने से तेज और पूरा project file download करने से कहीं तेज है
    • 1 घंटे का episode, 4 घंटे की high-quality studio recording के साथ effects और background music जोड़कर करीब 1 gigabyte audio पर निर्भर हो सकता है
  • तेज cold start के लिए upload के समय audio service का काम
    • original audio का backup
    • transcript view के लिए speech को transcribe करना
    • timeline view के लिए waveform बनाना
    • अगर 40 मिनट की recording में से सिर्फ 1 मिनट इस्तेमाल हो रहा है, तो ज़्यादातर clients को सिर्फ एक-दो छोटे pieces ही मिलें, इसके लिए उसे छोटे windows में slice करना
    • pieces को compressed format में transcode करना ताकि high-quality audio background में download होते हुए भी तुरंत चल सकने वाला lossy version मिल सके
  • UI data layer, user intent के अनुसार तुरंत ज़रूरी data के तेज version और वास्तव में उपयोग किए गए पूरे audio के high-quality version की loading manage करती है
    • browser की IndexedDB API multi-level caching और content-addressable storage के लिए उपयोगी है; automatic eviction management के साथ इसका मतलब है कि उपयोग हो तो data रहे, न हो तो गायब हो जाए
  • यह सारी processing और local caching पूरी होने के बाद, बाकी UI audio पर तेज random access मानकर editing workflow पर ध्यान दे सकता है

local-first app के बजाय server+browser UI क्यों बनाया?

  • Obsidian जैसे local-first apps पसंद हैं, जो बिना server के पूरी तरह काम करें—खासकर ऐसे रूप में जो भरोसेमंद escape hatch दें और साथ ही cloud-based paid experience भी हो
  • शुरुआत में Tauri app विकल्प से शुरू किया गया था, जिसमें local filesystem storage और optional server sync होता
    • UI को ऐसे data interface के आधार पर बनाया गया जिसे server या local app, दोनों दे सकें
    • यह भविष्य के लिए एक safety measure था, ताकि कोई भी funding app को lock-in के ज़रिए ज़्यादा monetize करने के लिए मजबूर न कर सके
  • बाद में समझ आया कि यह SaaS नहीं, बल्कि पार्टनर और कुछ दोस्तों के साथ इस्तेमाल करने की चीज़ है
    • गलत तरीके से इस्तेमाल करने की प्रोत्साहन खत्म हो गई और स्थायी संचालन लागत कम हो गई, इसलिए सबसे आसान तरीके से बनाना तय हुआ
  • जब लगभग 3 सेकंड का cold start हासिल हो गया, तो किसी को भी native app डाउनलोड और install करने में समय बर्बाद करना सही नहीं लगा
  • उम्मीद है कि audio apps मौजूदा desktop-only दुनिया से सीधे sync विकल्पों वाली local-first दुनिया में पहुँचें, और बीच के 10–20 साल के SaaS lock-in को छोड़ दें

क्या Automerge सुरक्षित है और web-scale है? क्या startup को इसका उपयोग करना चाहिए?

  • इसका जवाब खुशी से यह है कि पता नहीं; इसका मतलब इनकार नहीं, बल्कि सचमुच नहीं पता
  • जब लेखक ने नौकरी शुरू की थी, तब conflict-free real-time multiplayer editing जादू जैसी लगती थी, और 10 साल पहले इसके कुछ ज्ञात समाधान थे, लेकिन उनके लिए funded team और कई क्षेत्रों की विशेषज्ञता चाहिए होती थी
    • आज एक dependency लेकर, अधिकतर सहज तरीके से UI बनाया जा सकता है और दोस्तों के साथ real-time collaboration किया जा सकता है
  • security के लिहाज़ से अभी Ducking सीमित network access और Automerge server websocket connection बनाते समय authorization step से सुरक्षित है
    • users बिना invite वाले projects खोज या edit नहीं कर सकते
    • edits और comments की user attribution सिर्फ आंशिक रूप से सुरक्षित है और यह इस धारणा पर निर्भर करती है कि दोस्त शरारत नहीं करेंगे
    • सिर्फ comment की अनुमति, edit नहीं; project के कुछ हिस्सों पर ही edit; discovery control जैसी granular permissions के लिए सावधानीपूर्वक design work चाहिए
  • Ink & Switch द्वारा विकसित Keyhive cryptographically secure, capability-based access control model देता है
    • इससे Automerge apps को untrusted users के साथ भी आसानी से share किया जा सकेगा, लेकिन यह अभी तैयार नहीं है

क्या Automerge बेहतर है?

  • इस क्षेत्र में एक और समाधान Yjs है, लेकिन कौन-सा बेहतर है, इसका फैसला कोई और आपके लिए नहीं कर सकता
  • स्थायी सलाह
    • समस्या पर गहराई से सोचें, आने वाली सीमाओं के बारे में rough back-of-the-napkin calculation करें, अलग-अलग विकल्पों से prototypes बनाएँ, और ईमानदारी से मानें कि हो सकता है आपकी समस्या उतनी कठिन न हो कि उसके लिए नवीनतम और सबसे उन्नत समाधान ज़रूरी हो
  • Ducking के मामले में तेज prototyping और documentation exploration से यह स्पष्ट हुआ कि Automerge उस उपयोग के लिए काफ़ी mature और performant है
  • इससे भी अधिक महत्वपूर्ण यह है कि Ink & Switch ecosystem सौंदर्यबोध के स्तर पर आकर्षक लगता है
    • Automerge सिर्फ sync और versioning engine नहीं, बल्कि software को अधिक सुरक्षित, collaborative, flexible, आनंददायक और व्यक्तिगत बनाने वाले एक बड़े vision का हिस्सा है
    • Keyhive व अन्य प्रयासों की सफलता की उम्मीद के साथ, कुछ लोगों के लिए बने छोटे लेकिन जादुई software के प्रसार की आशा की गई है

अभी कोई टिप्पणी नहीं है.

अभी कोई टिप्पणी नहीं है.