प्रॉम्प्ट और स्कोप
आप एक फ़ाइल, ऑर्गनाइज़ेशन, या नॉलेज-ग्राफ़ API का रख-रखाव करते हैं जिसके रिसोर्स उपनामों (aliases) या बाइंडिंग्स के माध्यम से अन्य रिसोर्स की ओर इशारा कर सकते हैं। एक क्लाइंट WebDAV के Depth: infinity के समान रिकर्सिव एक्सपेंशन का अनुरोध करता है। ट्रैवर्सल, साइकिल रिपोर्टिंग, डेप्थ और नोड बजट डिज़ाइन करें, और बताएं कि 508 कब गलत होता है। यह बैकएंड, स्टोरेज और प्लेटफ़ॉर्म इंटरव्यू के लिए उपयुक्त है।
RFC 5842 लूप मिलने के बाद अनंत-गहराई (infinite-depth) वाले ऑपरेशन को समाप्त करने के लिए 508 को परिभाषित करता है; यह कोई सामान्य रीडायरेक्ट-लूप या CPU-टाइमआउट कोड नहीं है। मान लें कि ग्राफ़ टेनेंट्स के पार जा सकता है और प्रत्येक एज (edge) और नोड के लिए ऑथराइजेशन की आवश्यकता होती है।
इंटरव्यूअर क्या टेस्ट कर रहा है
- क्या आप स्टैक ओवरफ्लो की प्रतीक्षा करने के बजाय रिकर्सिव ट्रैवर्सल को एक ग्राफ़ के रूप में मॉडल करते हैं।
- क्या आप दोहराए गए नोड और वर्तमान पाथ पर मौजूद नोड के बीच अंतर करते हैं, और विभिन्न कार्यों के लिए ग्लोबल विज़िटेड और पाथ स्टेट का उपयोग करते हैं।
- क्या आप डेप्थ, नोड्स, एजेस, बाइट्स और समय के लिए बजट निर्धारित करते हैं, और फिर क्लाइंट के लिए कार्रवाई योग्य विफलता लौटाते हैं।
एक कमजोर उत्तर केवल अधिकतम रिकर्शन गहराई जोड़ता है। एक मजबूत उत्तर स्थिर रिसोर्स पहचान, पाथ साइकिल्स बनाम शेयर्ड सबग्राफ़्स, बजट की समाप्ति, 508 बाउंड्रीज़ और मल्टी-टेनेंट कैश सुरक्षा को कवर करता है।
पहले पूछे जाने वाले स्पष्टीकरण प्रश्न
- क्या संबंध एक ट्री, एक DAG, या एक मनमाना डायरेक्टेड ग्राफ़ है? डुप्लिकेट काम से बचने के लिए DAG को अभी भी विज़िटेड सेट की आवश्यकता होती है; एक मनमाने ग्राफ़ को वर्तमान-पाथ साइकिल डिटेक्शन की भी आवश्यकता होती है।
- क्या क्लाइंट को पूर्ण एक्सपेंशन, पेजिनेटेड परिणाम, या केवल रीचेबिलिटी की आवश्यकता है? आउटपुट कॉन्ट्रैक्ट यह निर्धारित करता है कि आंशिक परिणाम या कोई एसिंक्रोनस जॉब मान्य है या नहीं।
- क्या रिसोर्स IDs ग्लोबली यूनिक हैं? विज़िटेड कुंजियाँ बनाने से पहले उपनामों और क्रॉस-टेनेंट बाइंडिंग्स के लिए कैनोनिकल पहचान की आवश्यकता होती है।
- बजट को कौन नियंत्रित करता है? सेवा को अनिवार्य सीमाएं (hard limits) लागू करनी चाहिए; क्लाइंट द्वारा प्रदान की गई गहराई सीधे डेटाबेस या मेमोरी की खपत तय नहीं कर सकती।
30-सेकंड का उत्तर
“मैं संबंध को एक डायरेक्टेड ग्राफ़ के रूप में मॉडल करता हूँ और प्रत्येक रिसोर्स को एक स्थिर ID में कैनोनिकलाइज़ करता हूँ। ट्रैवर्सल के दौरान, मैं वास्तविक साइकिल्स का पता लगाने के लिए एक वर्तमान-पाथ सेट और साझा सबग्राफ़्स को फिर से विस्तारित करने से बचने के लिए एक ग्लोबल विज़िटेड सेट रखता हूँ। सेवा डेप्थ, नोड्स, एजेस, रिस्पॉन्स बाइट्स और वॉल टाइम पर सख्त सीमाएं लागू करती है। खोजी गई साइकिल 508 उत्पन्न कर सकती है; समाप्त हो चुके बजट एक स्पष्ट लिमिट एरर या एसिंक्रोनस जॉब स्थिति उत्पन्न करते हैं। परिणामों में एक संशोधित (redacted) साइकिल एज, ट्रंकेशन का कारण और अनुरोध ID शामिल होती है, कभी भी अनऑथराइज्ड नोड्स नहीं। टेस्ट्स सेल्फ़-साइकिल्स, एलियास साइकिल्स, शेयर्ड सबग्राफ़्स, डिनाइड एजेस और दुर्भावनापूर्ण गहरे ग्राफ़्स को कवर करते हैं।”
स्टेप-बाय-स्टेप समाधान
1. 508 की बाउंड्री परिभाषित करें
RFC 5842 तब 508 का उपयोग करता है जब एक रिकर्सिव रिसोर्स ऑपरेशन को अनंत लूप का सामना करना पड़ता है। साधारण URL रीडायरेक्ट्स को रीडायरेक्ट-चेन सुरक्षा की आवश्यकता होती है; टाइमआउट या समाप्त बजट के लिए अपनी स्वयं की त्रुटि की आवश्यकता होती है। स्टेटस विफलता के वर्ग की व्याख्या करता है, जबकि बॉडी डायग्नोस्टिक्स प्रदान करती है।
2. रिसोर्स पहचान को कैनोनिकलाइज़ करें
किसी उपनाम को टेनेंट, रिसोर्स प्रकार और अपरिवर्तनीय (immutable) ID के टुपल में हल करें। विज़िटेड कुंजियों के रूप में पाथ स्ट्रिंग्स, केस वेरिएंट्स, या विभिन्न URLs का उपयोग न करें। उपनाम समाधान को एक हॉप सीमा की भी आवश्यकता होती है ताकि ग्राफ़ ट्रैवर्सल शुरू होने से पहले यह लूप में न जाए।
3. पाथ और विज़िटेड स्थिति को अलग रखें
path वर्तमान DFS शाखा का प्रतिनिधित्व करता है; path में किसी नोड की ओर जाने वाली एज एक साइकिल है। visited इस अनुरोध के लिए पहले से पूरे किए गए या कतारबद्ध नोड्स का प्रतिनिधित्व करता है और हीरे के आकार के ग्राफ़ में डुप्लिकेट काम को हटाता है। एक संयुक्त सेट या तो कानूनी शेयरिंग को साइकिल के रूप में रिपोर्ट करता है या किसी अन्य शाखा पर साइकिल को छोड़ देता है।
4. बजट और ट्रंकेशन नियम निर्धारित करें
अधिकतम डेप्थ, नोड्स, एजेस, रिस्पॉन्स बाइट्स और वॉल-क्लॉक समय को सीमित करें। प्रति टेनेंट और अनुरोध पर बजट लागू करें, और डेटाबेस रीड्स को पेजिनेट करें। समाप्ति पर, काउंट्स, ट्रंकेशन का कारण और एक निरंतरता तंत्र (continuation mechanism) लौटाएं। यदि प्रोटोकॉल को पूर्ण परिणाम की आवश्यकता है, तो भ्रामक आंशिक ट्री लौटाने के बजाय एक एसिंक्रोनस ट्रैवर्सल जॉब बनाएं।
5. ऑथराइजेशन और कैशिंग को संभालें
प्रत्येक रिसोर्स को दृश्यमान परिणाम में जोड़ने से पहले उसे ऑथराइज करें। कैश कुंजियों में टेनेंट, अनुमति संस्करण और ट्रैवर्सल पैरामीटर शामिल होने चाहिए; अन्यथा एक टेनेंट साइकिल डायग्नोस्टिक्स से दूसरे टेनेंट के छिपे हुए नोड का अनुमान लगा सकता है। महंगे ग्राफ़्स के लिए, कैनोनिकल एजेस को कैश करें लेकिन प्रत्येक अनुरोध के लिए ऑथराइजेशन को फिर से जांचें।
6. रिस्पॉन्स का आकार चुनें
जब कोई साइकिल मिलती है और क्लाइंट डायग्नोस्टिक्स को समझता है, तो संशोधित साइकिल IDs, कट लोकेशन और अनुरोध ID के साथ 508 लौटाएं। यदि क्लाइंट बेस्ट एफर्ट चाहता है, तो truncated चिह्नित एक सफल पेजिनेटेड संग्रह लौटाएं; यह 508 की संपूर्ण-ऑपरेशन विफलता से भिन्न है। कारण का मिलान किए बिना डेटाबेस स्टैक ओवरफ्लो या प्रॉक्सी सेल्फ़-लूप को 508 के रूप में लेबल न करें।
7. हमलों और विफलता पाथ्स का परीक्षण करें
एक सेल्फ़-साइकिल, A-से-B-से-A, एक नोड के लिए एकाधिक उपनाम, एक साझा सबग्राफ़, ठीक सीमा पर गहराई, विशाल फ़ैन-आउट, एक अस्वीकृत क्रॉस-टेनेंट एज और टाइमआउट का परीक्षण करें। यह सुनिश्चित करें कि प्रत्येक नोड का अधिकतम एक बार विस्तार हो, अस्वीकृति से दृश्यमान काउंट्स न बदलें, और त्रुटियाँ छिपे हुए रिसोर्स IDs को प्रकट न करें।
उच्च गुणवत्ता वाला नमूना उत्तर
“मैं रिकर्सिव एक्सपेंशन को एक डायरेक्टेड-ग्राफ़ समस्या मानता हूँ। मैं उपनामों को एक टेनेंट और स्थिर रिसोर्स ID में हल करता हूँ, वास्तविक साइकिल्स के लिए वर्तमान-पाथ स्थिति का उपयोग करता हूँ, और साझा-सबग्राफ़ डिडुप्लिकेशन के लिए ग्लोबल विज़िटेड स्थिति का उपयोग करता हूँ। डेप्थ, नोड, एज, रिस्पॉन्स-साइज़ और समय के बजट सख्त सीमाएं हैं जिन्हें पेजिनेटेड प्रश्नों में पास किया जाता है। मैं 508 केवल तभी लौटाता हूँ जब रिकर्सिव ऑपरेशन वास्तव में एक साइकिल का सामना करता है और क्लाइंट उस अनुबंध का समर्थन करता है; साधारण रीडायरेक्ट और टाइमआउट अपनी स्वयं की त्रुटियों का उपयोग करते हैं। रिस्पॉन्स में केवल ऑथराइज्ड, संशोधित साइकिल डेटा और एक अनुरोध ID शामिल होता है। कैश कुंजियों में टेनेंट, अनुमति संस्करण और पैरामीटर शामिल होते हैं। टेस्ट्स सेल्फ़-साइकिल्स, एलियास साइकिल्स, डायमंड ग्राफ़्स, अस्वीकृत एजेस और दुर्भावनापूर्ण गहराई को कवर करते हैं।”
सामान्य गलतियाँ
- अधिकतम गहराई को साइकिल डिटेक्शन के बराबर मानना → मान्य गहरे ट्रीज विफल हो जाते हैं जबकि उथली साइकिल्स बनी रह सकती हैं → साइकिल्स के लिए पाथ स्थिति का और गहराई का केवल बजट के रूप में उपयोग करें।
- केवल ग्लोबल विज़िटेड बनाए रखना → एक साझा सबग्राफ़ को साइकिल के रूप में रिपोर्ट किया जाता है → वर्तमान पाथ को ग्लोबल ट्रैवर्सल स्थिति से अलग करें।
- प्रत्येक टाइमआउट के लिए 508 लौटाना → क्लाइंट ग्राफ़ साइकिल और ओवरलोड के बीच अंतर नहीं कर सकते → स्टेटस को वास्तविक कारण से मिलाएं।
- ऑथराइजेशन से पहले विस्तार करना → त्रुटि विवरण छिपे हुए नोड्स को लीक कर सकते हैं → दृश्यमान ट्रैवर्सल और गिनती से पहले ऑथराइज करें।
- कैश कुंजियों से अनुमति संस्करण छोड़ना → पुरानी पहुंच के परिणाम दृश्यमान रहते हैं → कैश प्रविष्टियों को टेनेंट, अनुमति संस्करण और मापदंडों से बांधें।
फॉलो-अप प्रश्न और उत्तर
यदि ग्राफ़ एक DAG है, तो वर्तमान-पाथ स्थिति क्यों बनाए रखें?
डेटा मॉडल एक DAG का वादा कर सकता है, लेकिन माइग्रेशन, उपनाम, या समवर्ती राइट्स (concurrent writes) अस्थायी रूप से इसका उल्लंघन कर सकते हैं। पाथ स्थिति एक किफायती रनटाइम सुरक्षा है; एक खोजी गई साइकिल को अपने राइट स्रोत की भी पहचान करनी चाहिए और नई बाइंडिंग्स को ब्लॉक करना चाहिए।
क्या आप 508 लौटा सकते हैं जब ग्राहक वह सभी नोड्स चाहता है जो मिले थे?
आंशिक डेटा को पूर्ण 508 विफलता के रूप में न छिपाएं। एक पेजिनेटेड या एसिंक्रोनस अनुबंध को परिभाषित करें जो पूर्ण पेज, ट्रंकेशन का कारण और एक निरंतरता कर्सर लौटाता है। 508 का उपयोग केवल तभी करें जब क्लाइंट को एटॉमिक पूर्ण विस्तार की आवश्यकता हो।
आप उच्च फ़ैन-आउट वाले टेनेंट को डेटाबेस समाप्त करने से कैसे रोकते हैं?
प्रति-टेनेंट समवर्तीता (concurrency), नोड, एज, क्वेरी-समय और रिस्पॉन्स-बाइट कोटा निर्धारित करें; बैच प्रीफ़ेच को सीमित करें और बैकप्रेशर लागू करें। बजट से अधिक अनुरोधों को कतारबद्ध करें या अस्वीकार करें, प्रति-टेनेंट खपत और विफलता के कारणों की निगरानी करें, और क्लाइंट को गहराई बढ़ाकर सीमाओं को बायपास न करने दें।