एक ब्राउज़र-आधारित Python playground, जो 5.5 MB का runtime लोड करता है, धीमे कनेक्शन वाले उपयोगकर्ताओं के लिए चुपचाप (silently) विफल होने लगा। इसका कारण Network Information API का गलत उपयोग और एक error-grouping dashboard था जिसने समस्या को गलत तरीके से लेबल कर दिया था। यह बग हफ्तों तक छिपा रहा, डेवलपर्स का समय बर्बाद किया, और उपयोगकर्ताओं के एक वर्ग को कोड चलाने में असमर्थ कर दिया।
समस्या कैसे सामने आई
Playground के error tracker ने एक एकल, ध्यान खींचने वाला संदेश दिखाया: “undefined is not an object.” शीर्षक से ऐसा लगा कि यह एक साधारण JavaScript typo है, इसलिए टीम ने एक ऐसे कोड पाथ (code path) की तलाश की जो अस्तित्व में ही नहीं था। जब उन्होंने रॉ मेटाडेटा (raw metadata) का निरीक्षण किया, तो उन्होंने देखा कि 89% घटनाएं वास्तव में network timeouts थीं। डैशबोर्ड ने आने वाली पहली त्रुटि (error) को लिया और उसका उपयोग पूरे बैच का नाम रखने के लिए किया, जिससे वास्तविक विफलता का प्रकार छिप गया।
सबक 1 – डैशबोर्ड के शीर्षक भ्रामक हो सकते हैं
एक डैशबोर्ड जो घटनाओं को एकत्रित (aggregate) करता है, वह तभी मदद करता है जब उसका एकत्रीकरण तर्क (aggregation logic) प्रत्येक घटना के वास्तविक कारण को दर्शाता हो। यहाँ, त्रुटि के कारण के बजाय स्थान (location) के आधार पर ग्रुपिंग करने से क्लाइंट-साइड बग की एक गलत तस्वीर पेश हुई। सीख: केवल डैशबोर्ड की हेडलाइन के आधार पर किसी समस्या को ठीक न करें। संसाधन आवंटित करने से पहले अंतर्निहित घटनाओं (underlying events) का एक नमूना लें और सत्यापित करें कि वास्तव में क्या हो रहा है।
सबक 2 – प्लेसहोल्डर मान (Placeholder values) माप नहीं होते हैं
धीमे लिंक वाले उपयोगकर्ताओं के लिए भारी runtime को लोड करने से बचने के लिए, कोड ने Network Information API का उपयोग किया और downlink प्रॉपर्टी को पढ़ा, जो megabits per second की रिपोर्ट करती है। पहली विज़िट पर, Chrome अक्सर वास्तविक माप के बजाय एक प्लेसहोल्डर लौटाता है। लॉजिक ने उस प्लेसहोल्डर को तेज़ कनेक्शन मान लिया और ऑप्टिमाइज़ेशन को छोड़ दिया, जिससे प्रभावी रूप से उन्हीं उपयोगकर्ताओं को बाधित कर दिया जिनकी मदद करने के लिए इसे बनाया गया था।
किसी भी डिफॉल्ट या सेंटिनल (sentinel) मान को "कोई डेटा नहीं" (no data) मानें। एक प्लेसहोल्डर को फॉलबैक रणनीति (fallback strategy) को ट्रिगर करना चाहिए, न कि उसे वास्तविक स्पीड रीडिंग के रूप में समझा जाना चाहिए।
सबक 3 – नेटवर्क की स्थिति बदलती रहती है, इसलिए एक सिंगल स्नैपशॉट अविश्वसनीय है
downlink समस्या के बाद, टीम ने effectiveType की जांच करने का विकल्प चुना, जो कनेक्शन को “4g”, “3g” आदि के रूप में वर्गीकृत करता है। एक त्वरित लैब टेस्ट सफल रहा, लेकिन कुछ ही क्षणों बाद वही टेस्ट दोबारा करने पर विफल हो गया। मोबाइल कनेक्शन में उतार-चढ़ाव होता रहता है; एक उपयोगकर्ता एक सेकंड में तेज़ 4G लिंक पर हो सकता है और अगले ही पल धीमे 3G पर गिर सकता है। केवल पेज लोड के समय कनेक्शन की जांच करना एक जुआ है।
सही तरीका यह है कि Network Information ऑब्जेक्ट पर change इवेंट को subscribe किया जाए और एक बार के निर्णय लेने के बजाय बैंडविड्थ में किसी भी बदलाव पर प्रतिक्रिया दी जाए।
टीम ने क्या बदला
- Two-stage download – अब runtime एक बहुत छोटी bootstrap फ़ाइल के साथ शुरू होता है। यदि कनेक्शन को धीमा पाया जाता है, तो bootstrap बाकी runtime को छोटे टुकड़ों (chunks) में प्राप्त करता है, जिससे पूरी तरह से प्रक्रिया रुकने की संभावना कम हो जाती है।
- Live monitoring – केवल एक बार
downlinkपढ़ने के बजाय, कोड अबchangeइवेंट्स को सुनता है और ज़रूरत के अनुसार डाउनलोड रणनीति को तुरंत (on the fly) बदल देता है। - Stable source selection – पहले सिस्टम तेज़ एंडपॉइंट दिखने पर डाउनलोड के बीच में ही CDN बदल देता था। धीमे लिंक पर इससे डाउनलोड शून्य से फिर से शुरू हो जाता था, जिससे समस्या और बढ़ जाती थी। नया लॉजिक डाउनलोड की अवधि के लिए सोर्स को लॉक कर देता है।
- Deferred cache writes – भारी कैश ऑपरेशन्स (cache operations), जो ऐप के उपयोग करने योग्य होने से पहले चलते थे, अब runtime शुरू होने के बाद तक के लिए टाल दिए गए हैं, जिससे महत्वपूर्ण डाउनलोड के लिए बैंडविड्थ खाली हो जाती है।
व्यापक प्रभाव
वेब-आधारित टूल बनाने वाले डेवलपर्स के लिए, नेटवर्क की परिवर्तनशीलता (variability) एक प्रमुख चिंता है। धीमे लिंक पर होने वाली साइलेंट विफलता उपयोगकर्ताओं को निराश करती है और टेलीमेट्री (telemetry) को गलत दिशा में ले जाती है, जिससे टीमें गलत डिबगिंग पथ पर चली जाती हैं। इस मामले में, डेटा की गलत व्याख्या के कारण हफ्तों तक निष्फल जांच करनी पड़ी।
आगे क्या ध्यान रखें
सीख: जब डेटा बहुत अधिक साफ-सुथरा (clean) लगे, तो संभावना है कि वह एक प्लेसहोल्डर है; जब डैशबोर्ड की हेडलाइन किसी एक बग की ओर इशारा करे, तो गहराई से जांच करें; और जब आप एक बार के नेटवर्क रीड के आधार पर निर्णय लेते हैं, तो आप एक अस्थिर लक्ष्य (moving target) पर दांव लगा रहे होते हैं। इन वास्तविकताओं के अनुसार खुद को ढालना साइलेंट विफलताओं को पूर्वानुमानित और सुधारात्मक घटनाओं में बदल देता है।
