प्रॉम्प्ट और संदर्भ
एक एडमिन कंसोल यूज़र को कई टैब खोलने की अनुमति देता है। जब यूज़र एक टैब में लॉग आउट करता है, थीम बदलता है, या नोटिफ़िकेशन अपडेट करता है, तो अन्य टैब तेज़ी से कन्वर्ज होने चाहिए। रिफ़्रेश, स्लीपिंग टैब, डुप्लिकेट मैसेज और बिना BroadcastChannel वाले ब्राउज़र फ़ाइनल स्टेट को करप्ट नहीं करने चाहिए। प्रोटोकॉल, रिकवरी, फ़ॉलबैक और वेरिफ़िकेशन मेट्रिक्स डिज़ाइन करें।
यह फ़्रंटएंड, वेब-प्लेटफ़ॉर्म और फ़्रंटएंड-सिस्टम-डिज़ाइन भूमिकाओं के लिए ब्राउज़र-कोऑर्डिनेशन का प्रश्न है। टैब की संख्या, सिंक डिले और इवेंट के प्रकार इंटरव्यू के अनुमान हैं, ब्राउज़र की गारंटी नहीं। BroadcastChannel की सेम-ओरिजिन और स्टोरेज-पार्टीशन सीमाओं, नॉन-पर्सिस्टेंट मैसेज के परिणामों, इवेंट-बनाम-स्टेट के चयन, और इसे localStorage, IndexedDB, SharedWorker या Web Locks के साथ कब जोड़ना है, इस पर ध्यान केंद्रित करें।
इंटरव्यूअर क्या टेस्ट कर रहा है
पहला, क्या आप API सीमा को स्पष्ट कर सकते हैं? BroadcastChannel उन विंडोज़, टैब, फ़्रेम और वर्कर्स के बीच मैसेज भेजता है जो एक ओरिजिन और कम्युनिकेबल स्टोरेज पार्टीशन शेयर करते हैं। यह क्रॉस-ओरिजिन ट्रांसपोर्ट, ड्यूरेबल कतार या डिस्ट्रिब्यूटेड-कंसिस्टेंसी सर्विस नहीं है।
दूसरा, क्या आप एक इडेम्पोटेंट (idempotent) प्रोटोकॉल डिज़ाइन कर सकते हैं? मैसेज डुप्लिकेट हो सकते हैं, सेंडर को अपना खुद का ब्रॉडकास्ट नहीं मिलता है, और रिसीव करने वाला पेज बंद हो सकता है या स्लीप मोड में जा सकता है। बिना किसी वर्ज़न और री-रीड पाथ के केवल "थीम बदल गई" कहने वाला मैसेज स्टेट को स्थायी रूप से पुराना (stale) छोड़ देता है।
तीसरा, क्या आप नोटिफ़िकेशन को सोर्स ऑफ़ ट्रुथ (source of truth) से अलग कर सकते हैं? लॉगआउट अमान्यकरण (invalidation) ब्रॉडकास्ट कर सकता है, थीम परिवर्तनों को पर्सिस्ट करके फिर घोषित किया जा सकता है, और नोटिफ़िकेशन अपडेट को रिसीवर्स से एक आधिकारिक कैश को फिर से पढ़ने के लिए कहना चाहिए, न कि मैसेज में पूरी सूची को सत्य मानना चाहिए।
अंत में, क्या आप लाइफ़साइकल और फ़ॉलबैक को संभाल सकते हैं: चैनल बंद करना, मैसेज से टोकन बाहर रखना, क्षमता का पता लगाना, स्टोरेज इवेंट या सर्वर री-रीड का उपयोग करना, और यह मापना कि सिंक्रोनाइज़ेशन कोई लूप या मेमोरी लीक न बनाए?
पहले स्पष्ट करने वाले प्रश्न
- क्या पेलोड एक बार का इवेंट है, वर्तमान स्थिति (current state) है, या दोबारा चलाने योग्य इतिहास (replayable history) है? यह तय करता है कि एक पर्सिस्टेंट वर्ज़न की आवश्यकता है या नहीं।
- क्या दायरा एक ओरिजिन है, उसी टॉप-लेवल साइट के तहत एक iframe है, या अलग-अलग सबडोमेन हैं? ओरिजिन संबंधित दिखने पर भी स्टोरेज पार्टीशन संचार को रोक सकता है।
- क्या कोई मैसेज खो सकता है? लॉगआउट, परमिशन निरस्तीकरण और एडिट कॉन्फ़्लिक्ट के लिए अलग-अलग रिकवरी गारंटी की आवश्यकता होती है।
- सोर्स ऑफ़ ट्रुथ कहाँ है: सर्वर, IndexedDB, localStorage, इन-मेमोरी कैश, या सर्विस वर्कर?
- क्या रिफ़्रेश, माइग्रेशन या बैच वर्क के लिए केवल एक टैब ही एकमात्र राइटर (writer) होना चाहिए? BroadcastChannel कोई लॉक प्रदान नहीं करता है।
- प्राइवेट मोड, बैकग्राउंड फ़्रीज़िंग और अपेक्षित टैब काउंट सहित ब्राउज़र मैट्रिक्स क्या है?
- क्या किसी मैसेज में प्रोफ़ाइल डेटा, परमिशन या टोकन हो सकता है? यदि ऐसा है, तो इसे एक नॉन-सेंसिटिव इनवैलिडेशन सिग्नल से बदलें।
30-सेकंड का उत्तर
"मैं BroadcastChannel को एक लो-लेटेंसी नोटिफ़िकेशन बस के रूप में उपयोग करूँगा, न कि एक ड्यूरेबल स्टेट सोर्स के रूप में। प्रत्येक मैसेज में एक प्रोटोकॉल वर्ज़न, इवेंट प्रकार, मोनोटोनिक सीक्वेंस या स्टेट वर्ज़न और ट्रेस ID होती है। रिसीवर शेप को वैलिडेट करते हैं, इवेंट को इडेम्पोटेंट तरीके से लागू करते हैं, और वर्ज़न गैप दिखाई देने पर localStorage, IndexedDB, या सर्वर को फिर से पढ़ते हैं। लॉगआउट इनवैलिडेशन भेजता है, थीम पर्सिस्टेंट प्राथमिकताओं को लिखती है, और नोटिफ़िकेशन परिवर्तन री-रीड ट्रिगर करते हैं। यदि API अनुपलब्ध है, तो स्टोरेज इवेंट या पोलिंग का उपयोग करें; यदि एक ही राइटर आवश्यक है, तो Web Locks या सर्वर कोऑर्डिनेशन का उपयोग करें। टियरडाउन पर हर चैनल को बंद करें और लेटेंसी, खोए हुए मैसेज की रिकवरी और डुप्लिकेट हैंडलिंग को मापें।"
स्टेप-बाय-स्टेप उत्तर
स्टेप 1: मैसेज और आधिकारिक स्टेट को परिभाषित करें
प्रत्येक फ़ीचर के लिए एक सोर्स ऑफ़ ट्रुथ असाइन करें। थीम और भाषा ऐसी प्राथमिकताएं हैं जो पर्सिस्टेंट सेटिंग्स में रह सकती हैं। नोटिफ़िकेशन और अनुमतियों को सर्वर या स्थानीय कैश से फिर से पढ़ा जाना चाहिए। लॉगआउट एक सेशन-इनवैलिडेशन सिग्नल है; मैसेज में कभी भी एक्सेस टोकन न डालें। केवल नॉन-सेंसिटिव type, version, entityKey, updatedAt, या traceId ब्रॉडकास्ट करें।
MDN बताता है कि BroadcastChannel सेम-ओरिजिन ब्राउज़िंग कॉन्टेक्स्ट और वर्कर्स के बीच द्विदिशात्मक संचार (bidirectional communication) का समर्थन करता है, जबकि एप्लिकेशन मैसेज प्रोटोकॉल को परिभाषित करता है; प्लेटफ़ॉर्म कोई बातचीत (negotiation) प्रदान नहीं करता है। वर्शनिंग, अज्ञात-इवेंट हैंडलिंग और फ़ील्ड वैलिडेशन एप्लिकेशन की ज़िम्मेदारियां हैं।
स्टेप 2: डुप्लिकेट, ऑर्डरिंग और लॉस को संभालें
प्रत्येक स्टेट डोमेन के लिए अंतिम प्रोसेस्ड वर्ज़न बनाए रखें। उस मैसेज को अनदेखा करें जिसका वर्ज़न पुराना या बराबर है; एक नया वर्ज़न एक बार फिर से पढ़ने (री-रीड) को ट्रिगर कर सकता है; एक बड़ा अंतर (jump) गैप को चिह्नित करता है और स्नैपशॉट सिंक शुरू करता है। यदि बिज़नेस बिना वर्ज़न के इवेंट दिखाता है, तो डिडुप्लिकेशन ID और एक बाउंडेड प्रोसेस्ड सेट का उपयोग करें, यह स्वीकार करते हुए कि यह साबित नहीं कर सकता कि कोई मध्यवर्ती इवेंट खो नहीं गया था।
डिलीवरी को मानकर न चलें। सेंडर को अपना मैसेज नहीं मिलता है, और नया खुला या स्लीपिंग टैब इसे मिस कर सकता है। स्टार्टअप पर, सब्सक्राइब करने से पहले पर्सिस्टेंट स्टेट या सर्वर स्नैपशॉट लोड करें; ब्रॉडकास्ट केवल फ्रेशनेस लेटेंसी को कम करता है।
स्टेप 3: पर्सिस्टेंस और कोऑर्डिनेशन को एक साथ चुनें
localStorage छोटी प्राथमिकताओं के लिए उपयुक्त है और स्टोरेज इवेंट को ट्रिगर कर सकता है; यह हाई-थ्रूपुट डेटाबेस या टोकन रखने की जगह नहीं है। IndexedDB बड़े लोकल कैश और वर्ज़न वाले स्नैपशॉट के लिए उपयुक्त है। एक Service Worker बैकग्राउंड सिंक में भाग ले सकता है, लेकिन इसे रिकवरेबल स्टोरेज में परिणाम लिखने चाहिए।
BroadcastChannel कई कॉन्टेक्स्ट के लिए नोटिफ़िकेशन की समस्या हल करता है, सिंगल-राइटर कोऑर्डिनेशन की नहीं। यदि केवल एक टैब को कैश रिफ़्रेश करना है, माइग्रेशन चलाना है, या बैच सबमिट करना है, तो Web Locks का उपयोग करें। लॉक के बिना, एक वर्ज़न शर्त शामिल करें और सर्वर को मध्यस्थता करने दें। SharedWorker साझा कनेक्शन या सेंट्रलाइज़्ड स्टेट के लिए उपयुक्त है, लेकिन लाइफ़साइकल और कम्पैटिबिलिटी जटिलता जोड़ता है।
स्टेप 4: सुरक्षित रिसेप्शन और फ़ॉलबैक बनाएं
केवल अनुमति प्राप्त (allowlisted) इवेंट प्रकारों को स्वीकार करें, मैसेज के आकार को सीमित करें, और अज्ञात वर्ज़न या अमान्य स्कीमा को अस्वीकार करें। मैसेज में कभी भी एक्सेस टोकन, पूरी प्रोफ़ाइल या निष्पादन योग्य HTML न रखें। लॉगआउट पर, संवेदनशील स्थानीय कैश साफ़ करें और साइन-इन पर जाएं; थीम इवेंट पर, UI अपडेट करें लेकिन पर्सिस्ट की गई सेटिंग पर भरोसा करें।
यदि कैपेबिलिटी डिटेक्शन विफल हो जाता है, तो छोटे स्टेट के लिए स्टोरेज इवेंट का उपयोग करें। यदि वह अनुपलब्ध या विभाजित है, तो फ़ोकस पर दोबारा पढ़ें, संक्षेप में पोल करें, या सर्वर पुश का उपयोग करें। फ़ॉलबैक को दोहराना सुरक्षित होना चाहिए; ब्रॉडकास्ट की कमी स्थायी विचलन नहीं बननी चाहिए।
स्टेप 5: रिसोर्स मैनेज करें और व्यवहार को सत्यापित करें
जब कोई कंपोनेंट या पेज नष्ट हो जाए तो लिसनर्स को हटाएं और close() को कॉल करें। प्रत्येक रेंडर पर नया चैनल न बनाएं। नेमस्पेस का उपयोग करें ताकि असंबंधित एप्लिकेशन समान नाम की सदस्यता न लें। एक सोर्स लेबल और ट्रेस ID शामिल करें ताकि रिसीवर लूप में उसी मैसेज को दोबारा ब्रॉडकास्ट न करे।
मल्टी-टैब एंड-टू-एंड डिले, डुप्लिकेट और रीऑर्डरिंग, स्लीप के बाद फिर से शुरू होना, रिफ़्रेश के बाद शुरुआती स्नैपशॉट, स्टोरेज फ़ॉलबैक, स्टोरेज-पार्टीशन आइसोलेशन, चैनल क्लोज़र, बड़े आकार के मैसेज, लूप और यूज़र स्विचिंग का परीक्षण करें। हैंडलर की सफलता, वर्ज़न गैप, री-रीड, छोड़े गए डुप्लिकेट, रिकवरी समय और खुले छोड़े गए चैनलों को ट्रैक करें।
मॉडल उच्च-गुणवत्ता वाला उत्तर
"मैं BroadcastChannel को एक नोटिफ़िकेशन बस के रूप में परिभाषित करूँगा, कतार के रूप में नहीं। लॉगआउट में केवल एक सेशन-इनवैलिडेशन प्रकार और वर्ज़न होता है। एक थीम अपडेट localStorage में लिखता है और नई प्राथमिकता वर्ज़न को ब्रॉडकास्ट करता है। एक नोटिफ़िकेशन अपडेट एक इकाई कुंजी और वर्ज़न को ब्रॉडकास्ट करता है, ताकि प्रत्येक रिसीवर सर्वर या IndexedDB से दोबारा पढ़े। मैसेज में कोई टोकन या पूरा यूज़र डेटा नहीं होता है।
प्रत्येक मैसेज में एक प्रोटोकॉल वर्ज़न, मोनोटोनिक स्टेट वर्ज़न और ट्रेस ID होती है। रिसीवर अज्ञात शेप्स को अस्वीकार करते हैं, प्रोसेस्ड या पुराने वर्ज़न को छोड़ देते हैं, और जब वे गैप देखते हैं तो एक स्नैपशॉट प्राप्त करते हैं। स्टार्टअप सब्सक्राइब करने से पहले एक स्नैपशॉट लोड करता है क्योंकि एक नया या स्लीपिंग टैब ब्रॉडकास्ट मिस कर सकता है, और सेंडर को अपना खुद का मैसेज नहीं मिलता है।
यदि कैश रिफ़्रेश के लिए एक राइटर की आवश्यकता है, तो मैं Web Locks जोड़ूँगा; BroadcastChannel अकेले दो टैब को एक साथ लिखने से नहीं रोक सकता। असमर्थित ब्राउज़र छोटी प्राथमिकताओं के लिए स्टोरेज इवेंट और अन्य डेटा के लिए फ़ोकस-टाइम री-रीड या शॉर्ट पोलिंग का उपयोग करते हैं। टियरडाउन लिसनर्स को हटाता है और चैनल को बंद करता है। मेट्रिक्स डिले, गैप, डुप्लिकेट, रिकवरी समय और लीक हुए रिसोर्स को कवर करते हैं। यह लो-लेटेंसी नोटिफ़िकेशन, रिकवरेबल स्टेट और ब्राउज़र कम्पैटिबिलिटी को अलग करता है।"
सामान्य विफलता मोड
- ब्रॉडकास्ट को एक ड्यूरेबल कतार मानना → नए या स्लीपिंग टैब इवेंट मिस कर देते हैं → पहले एक स्नैपशॉट लोड करें और मैसेज को संकेत के रूप में उपयोग करें।
- मैसेज में टोकन या पूरा स्टेट डालना → संवेदनशील-डेटा एक्सपोज़र और वर्ज़न टकराव को बढ़ाता है → केवल नॉन-सेंसिटिव इवेंट, कुंजियां और वर्ज़न भेजें।
- कोई वर्ज़न या डिडुप्लिकेशन ID न होना → डुप्लिकेट और रीऑर्डरिंग UI को पीछे ले जाते हैं → मोनोटोनिक वर्ज़न, इडेम्पोटेंट हैंडलिंग और गैप री-रीड का उपयोग करें।
- यह मानना कि सेम-ओरिजिन का मतलब गारंटीड कनेक्टिविटी है → स्टोरेज पार्टीशनिंग कॉन्टेक्स्ट को अलग कर सकती है → वास्तविक सीमा का परीक्षण करें और फ़ॉलबैक प्रदान करें।
- BroadcastChannel को लॉक के रूप में उपयोग करना → दो टैब अभी भी एक साथ लिख सकते हैं → Web Locks या कंडीशनल सर्वर राइट्स का उपयोग करें।
- हर रेंडर पर एक चैनल बनाना → लिसनर्स और रिसोर्स लीक होते हैं → एक स्थिर इंस्टेंस रखें, लिसनर्स को हटाएं और इसे बंद करें।
- प्राप्त प्रत्येक मैसेज को दोबारा ब्रॉडकास्ट करना → एक लूप बनाता है → सोर्स/ट्रेस ID ले जाएं और केवल स्टेट बदलने पर भेजें।
- स्टोरेज इवेंट को पूर्ण प्रतिस्थापन मानना → वे केवल कुछ राइट्स को कवर करते हैं और उसी विंडो को नहीं → अंतर को स्पष्ट करें और री-रीड जोड़ें।
फ़ॉलो-अप प्रश्न
फ़ॉलो-अप 1: दो टैब एक ही फ़ॉर्म को संपादित करते हैं। आप ओवरराइटिंग से कैसे बचते हैं?
ब्रॉडकास्ट करें कि रिसोर्स वर्ज़न बदल गया है; स्थानीय ड्राफ़्ट को ओवरराइट न करें। एक बेस वर्ज़न सबमिट करें, सर्वर को पुराने कंडीशनल राइट्स को अस्वीकार करने दें, और यूज़र मर्ज के लिए कॉन्फ़्लिक्ट दिखाएं। स्थानीय प्राथमिकता क्रमबद्ध (serialized) राइट्स के लिए Web Locks का उपयोग कर सकती है।
फ़ॉलो-अप 2: एक टैब 20 मिनट तक स्लीप रहने के बाद जागता है। यह कैसे तालमेल बिठाता है?
रिज्यूमे पर सर्वर या IndexedDB स्नैपशॉट को दोबारा पढ़ें, स्टेट वर्ज़न की तुलना करें, और फिर किसी भी वृद्धिशील सिग्नल को प्रोसेस करें। अंतिम ब्रॉडकास्ट पर भरोसा न करें। यदि स्नैपशॉट अनुपलब्ध है, तो स्थिति को पुराना चिह्नित करें और पुनर्मूल्यांकन की मांग करें या एक स्पष्ट समाप्त स्थिति दिखाएं।
फ़ॉलो-अप 3: अलग-अलग सबडोमेन के पेजों को संचार करने की आवश्यकता है। क्या BroadcastChannel इसे हल करता है?
यह न मानें कि यह हल करता है। BroadcastChannel ओरिजिन और स्टोरेज पार्टीशन द्वारा विवश है। क्रॉस-ओरिजिन संचार के लिए ओरिजिन, स्कीमा और अनुमति जांच के साथ एक स्पष्ट postMessage विंडो संबंध या सर्वर समन्वय की आवश्यकता होती है; केवल एक चैनल साझा करने के लिए सुरक्षा सीमा को कमजोर न करें।
फ़ॉलो-अप 4: केवल एक टैब को WebSocket बनाए रखना चाहिए। आप इसे कैसे डिज़ाइन करेंगे?
BroadcastChannel कनेक्शन स्थिति और डेटा साझा कर सकता है लेकिन एक लीडर का चुनाव नहीं कर सकता। होल्डर के लिए Web Locks को प्राथमिकता दें, अन्य टैब इसके ब्रॉडकास्ट की सदस्यता लें; होल्डर के बंद होने या लॉक खोने के बाद फिर से चुनाव करें। यदि अनुपलब्ध है, तो सर्वर लीज का उपयोग करें या सर्वर-साइड डिडुप्लिकेशन और एक स्पष्ट लागत ट्रेड-ऑफ़ के साथ कई कनेक्शनों की अनुमति दें।