प्रॉम्प्ट और संदर्भ
जब Tokio select! किसी टाइमआउट, कैंसलेशन टोकन और I/O की प्रतीक्षा करता है, तो आप यह कैसे निर्धारित करते हैं कि कोई future कैंसलेशन-सुरक्षित (cancellation-safe) है या नहीं? यदि आंशिक रूप से पूर्ण हुआ ऑपरेशन रद्द हो जाता है, तो आप उसे कैसे रिकवर करते हैं?
यह Rust, बैकएंड, इंफ्रास्ट्रक्चर और एसिंक्रोनस-सर्विस भूमिकाओं के लिए उपयुक्त है। Tokio कैंसलेशन को future को ड्रॉप करने के रूप में परिभाषित करता है; जीतने वाली select! ब्रांच जारी रहती है जबकि अन्य ब्रांचों को किसी भी .await पर ड्रॉप किया जा सकता है। मुख्य अंतर प्रतीक्षा को रोकने बनाम किसी बाहरी साइड इफ़ेक्ट को पूर्ववत (undo) करने का है, जिसके लिए एक ऐसी स्टेट मशीन की आवश्यकता होती है जो सुरक्षित रूप से पुनरारंभ (restart) हो सके।
इंटरव्यूअर क्या जांच रहा है
- यह समझना कि future को ड्रॉप करने से अंतर्निहित I/O या रिमोट साइड इफ़ेक्ट रोलबैक नहीं होते हैं।
- रीड बफ़र्स, क्यू, लॉक्स और प्रोटोकॉल फ़्रेम में आंशिक प्रगति (partial progress) की पहचान करना।
- पुनरारंभ के बाद डेटा लॉस या डुप्लिकेट सबमिशन को रोकने के लिए ओनरशिप, स्टेट मशीन और आइडेम्पोटेंसी कीज़ का उपयोग करना।
- यह जानना कि कौन से Tokio प्रिमिटिव्स कैंसलेशन सुरक्षा को डॉक्यूमेंट करते हैं और किन्हें रैपर की आवश्यकता होती है।
- abort, टाइमआउट, ग्रेसफुल शटडाउन और बाहरी कैंसलेशन के बीच अंतर करना।
- मॉडल टेस्ट, फॉल्ट इंजेक्शन और मेट्रिक्स के साथ कैंसलेशन पाथ्स को सत्यापित करना।
30-सेकंड उत्तर फ्रेमवर्क
“मैं पहले कैंसलेशन बाउंड्री को परिभाषित करता हूँ: किसी future को ड्रॉप करने से उस टास्क की पोलिंग बंद हो जाती है, लेकिन यह गारंटी नहीं मिलती कि रिमोट ऑपरेशन पूर्ववत हो गया है। एक future केवल तभी कैंसलेशन-सुरक्षित होता है यदि किसी भी await के बाद उसे ड्रॉप करने और फिर से कॉल करने पर वह सही ढंग से फिर से शुरू (resume) या पुनः प्रयास (retry) कर सके। मैं कंज्यूम किए गए बाइट्स, रिक्वेस्ट IDs, बफ़र्स और आइडेम्पोटेंसी कीज़ को एक ओन्ड (owned) स्टेट मशीन में रखता हूँ; अपरिवर्तनीय प्रभावों को पर्सिस्ट किया जाता है या पुष्टि के लिए await किया जाता है। टेस्ट प्रत्येक await पॉइंट पर कैंसलेशन इंजेक्ट करते हैं।”
चरण-दर-चरण विस्तृत विश्लेषण
चरण 1: कैंसलेशन पॉइंट्स को चिह्नित करें
एसिंक फ़ंक्शन में प्रत्येक .await की समीक्षा करें। क्या इसने पहले ही लोकल या रिमोट स्टेट को बदल दिया है, और यदि future को वहीं ड्रॉप कर दिया जाता है तो कौन से फ़ील्ड रिकवर हो सकते हैं? केवल एंट्री और एग्जिट का परीक्षण करने के बजाय नेटवर्क रीड और राइट, लॉक वेट, चैनल रिसीव और स्लीप को कैंसलेशन पॉइंट के रूप में मानें।
चरण 2: कैंसलेशन को पूर्ववत (undo) करने से अलग करें
select! ब्रांच को रद्द करने पर आमतौर पर उसका future ड्रॉप हो जाता है; रिमोट सर्विस को पहले ही भेजा गया अनुरोध जारी रह सकता है। एक टाइमआउट हैंडलर विफलता चिह्नित करने और गैर-आइडेम्पोटेंट ऑपरेशन को आँख मूंदकर दोबारा भेजने के बजाय रिक्वेस्ट ID और अज्ञात-परिणाम (unknown-result) स्थिति रिकॉर्ड करता है। यदि पूर्ववत (undo) समर्थित है, तो प्रोटोकॉल के कैंसलेशन ऑपरेशन को कॉल करें और उसकी पुष्टि का await करें।
चरण 3: एक रिकवरेबल स्टेट मशीन डिज़ाइन करें
तैयारी (preparation), सेंड (send), अवेट-कन्फर्मेशन (await-confirmation), कमिटेड (committed) और कंपनसेशन (compensation) स्थितियों का प्रतिनिधित्व करें। एक स्पष्ट ओनर स्टेट और बफ़र्स को बनाए रखता है; एक रीस्टार्ट यह चुनता है कि पढ़ना जारी रखना है, दोबारा भेजना है, परिणाम की जांच करनी है या क्षतिपूर्ति (compensate) करनी है। स्ट्रीमिंग प्रोटोकॉल के लिए, फ़्रेम सीमाओं और कन्फ़र्म्ड ऑफ़सेट्स को रिकॉर्ड करें ताकि किसी आंशिक संदेश की बीच से गलत व्याख्या न हो।
चरण 4: क्यू और लॉक्स को सुसंगत रखें
चैनल या स्ट्रीम आइटम प्राप्त करने के बाद लेकिन टिकाऊ (durable) प्रोसेसिंग से पहले रद्द करने पर एक ऐसा आइटम बनता है जो उपभोग (consumed) तो हो गया लेकिन पूरा नहीं हुआ। ट्रांज़ैक्शनल एक्नॉलेजमेंट, रिपीटेबल रीड्स या एक ड्यूरेबल लीज़ का उपयोग करें। select! ब्रांच के अंदर एकमात्र कॉपी को किसी टेम्पररी वेरिएबल में पॉप न करें। लॉक गार्ड ड्रॉप होने पर शेयर्ड स्टेट को रिलीज़ करता है, जबकि रिकवरी यह रिकॉर्ड करती है कि संरक्षित ऑपरेशन कमिट हुआ या नहीं।
चरण 5: संसाधन और टास्क समाप्ति का प्रबंधन करें
JoinHandle::abort किसी टास्क को रोकता है लेकिन व्यावसायिक क्लीनअप की जगह नहीं लेता है। सॉकेट्स, फ़ाइलों, टेम्पररी फ़ाइलों और सेमाफ़ोर परमिट्स के लिए RAII गार्ड्स का उपयोग करें। जो कार्य जारी रहना चाहिए वह एक रिटेन्ड हैंडल वाले अलग टास्क में होना चाहिए। ग्रेसफुल शटडाउन नए कार्य को स्वीकार करना बंद कर देता है, समाप्त होने योग्य ऑपरेशन्स की प्रतीक्षा करता है, और फिर शेष के लिए कैंसलेशन का संकेत देता है और रिकॉर्ड करता है।
चरण 6: कैंसलेशन सुरक्षा सत्यापित करें
प्रत्येक await से पहले और बाद में कैंसलेशन इंजेक्ट करें, रीस्टार्ट, डुप्लिकेशन, लॉस और रिसोर्स लीक की जाँच करें। नियंत्रित नकली I/O, एक मॉडल स्टेट मशीन और कॉनक्रेन्सी टेस्ट्स टाइमआउट, चैनल क्लोज़, पीयर डिस्कनेक्ट और टास्क अबॉर्ट को कवर करते हैं। इन-फ़्लाइट अनुरोधों, डुप्लिकेट-की हिट्स, कंपनसेशन काउंट, कैंसलेशन लेटेंसी और लीक हुए परमिट्स को ट्रैक करें; इन मेट्रिक्स के बिना “रद्द” केवल एक धारणा है।
ट्रेड-ऑफ़, सीमाएँ और सूचना लाभ
कैंसलेशन सुरक्षा का अर्थ है कि एसिंक कंट्रोल फ़्लो बाधित होने पर भी व्यावसायिक स्थिति स्पष्ट करने योग्य बनी रहे। बिना किसी बाहरी प्रभाव वाले छोटे futures को पुनरारंभ करना आसान है; नेटवर्क, डेटाबेस और क्यू ऑपरेशन्स को आइडेम्पोटेंसी, पुष्टि और कंपनसेशन की आवश्यकता होती है। प्रत्येक कार्य को गैर-रद्द करने योग्य (uncancellable) बनाने से रिसोर्स बग छिप जाते हैं और शटडाउन लेटेंसी बढ़ जाती है, इसलिए केवल स्पष्ट एटॉमिक सीमाओं की सुरक्षा करें।
मॉडल उच्च-गुणवत्ता वाला उत्तर
“मैं प्रत्येक .await को एक कैंसलेशन पॉइंट मानता हूँ और पूछता हूँ कि इससे पहले क्या साइड इफ़ेक्ट हुआ और ड्रॉप से कैसे रिकवर किया जाए। Tokio select! हारने वाले future को ड्रॉप कर देता है; यह पहले से भेजे गए अनुरोध को पूर्ववत नहीं करता है। इसलिए एक टाइमआउट रिक्वेस्ट ID को बनाए रखता है और केवल आइडेम्पोटेंसी की के साथ या परिणाम की जांच करने के बाद ही पुनः प्रयास करता है। ऑपरेशन स्टेट मशीन तैयारी, सेंड, पुष्टि की प्रतीक्षा, कमिटेड और कंपनसेशन के बीच अंतर करती है।
चैनल रिसीव, फ़ाइल राइट और डेटाबेस कमिट को ट्रांज़ैक्शनल एक्नॉलेजमेंट या रिपीटेबल रीड्स की आवश्यकता होती है ताकि उपभोग किया गया आइटम नष्ट न हो। RAII गार्ड्स संसाधनों को रिलीज़ करते हैं, और जिस कार्य को समाप्त होना चाहिए वह एक देखे गए (observed) हैंडल के साथ एक अलग टास्क में रहता है। ग्रेसफुल शटडाउन रद्द करने और प्रतीक्षा करने से पहले नए इनटेक को रोक देता है।
मैं प्रत्येक await पर कैंसलेशन इंजेक्ट करता हूँ, रीस्टार्ट, डुप्लिकेशन, लॉस और लीक्स का परीक्षण करता हूँ, और इन-फ़्लाइट कार्य, डुप्लिकेट कीज़, कंपनसेशन, कैंसलेशन लेटेंसी और परमिट्स की निगरानी करता हूँ। यह केवल यह दिखाने के बजाय कि कोई टास्क रुक गया, कैंसलेशन सुरक्षा को प्रदर्शित करता है।”
सामान्य गलतियाँ
- ड्रॉप को रिमोट कैंसलेशन मानना → अनुरोध पहले से ही चल रहा हो सकता है → इसकी ID बनाए रखें, इसे क्वेरी करें, या स्पष्ट कैंसल API का उपयोग करें।
- संदेश का उपभोग करने के बाद कैंसलेशन पर विचार करना → एकमात्र कॉपी गायब हो सकती है → एक्नॉलेजमेंट, लीज़ या रिपीटेबल रीड्स का उपयोग करें।
- टाइमआउट के बाद आँख मूंदकर दोबारा भेजना → राइट का दोहरा प्रभाव हो सकता है → पहले आइडेम्पोटेंसी की का उपयोग करें या स्टेट क्वेरी करें।
- केवल फ़ंक्शन एंट्री का परीक्षण करना → रेस कंडीशन awaits के बीच होती हैं → प्रत्येक await पर कैंसलेशन इंजेक्ट करें।
- क्लीनअप के बजाय abort का उपयोग करना → फ़ाइलें, लॉक्स और परमिट लीक हो सकते हैं → गार्ड्स और शटडाउन प्रोटोकॉल का उपयोग करें।
- प्रत्येक टास्क को गैर-रद्द करने योग्य बनाना → ग्रेसफुल शटडाउन हमेशा के लिए प्रतीक्षा कर सकता है → केवल वास्तविक एटॉमिक सीमाओं की सुरक्षा करें।
फ़ॉलो-अप प्रश्न और उत्तर
आपको कैसे पता चलेगा कि कोई Tokio प्रिमिटिव कैंसलेशन-सुरक्षित है या नहीं?
इसके दस्तावेज़ में इस स्पष्ट गारंटी की जाँच करें कि select! के अंदर रद्द करने और इसे फिर से कॉल करने से डेटा नष्ट नहीं होता है। उस गारंटी के बिना, यह मान लें कि आंशिक प्रगति खो सकती है, स्थिति सहेजें, और रिकवरी टेस्ट लिखें।
आपको कैसे पता चलेगा कि टाइमआउट के बाद डेटाबेस राइट समाप्त हो गया है?
परिणाम की जांच करने के लिए क्लाइंट रिक्वेस्ट ID और एक यूनिक कंस्ट्रेंट का उपयोग करें, या एक क्वेरी करने योग्य ऑपरेशन स्थिति प्रदर्शित करें। केवल क्लाइंट टाइमआउट किसी गैर-आइडेम्पोटेंट राइट को दोहराने की अनुमति नहीं है।
क्या आप JoinHandle::abort के तुरंत बाद संसाधनों को हटा सकते हैं?
केवल टास्क के रुकने और उसके रिसोर्स ड्रॉप्स के पूरा होने के बाद। जॉइन परिणाम का await करें या ओनिंग गार्ड को क्लीनअप करने दें; अबॉर्ट जारी करना सिंक्रोनस पूर्णता नहीं है।
कार्य को कब एक अलग टास्क में ले जाना चाहिए?
जिस कार्य को पूरा होना आवश्यक है, जिसमें क्रॉस-रिक्वेस्ट पुनः प्रयासों की आवश्यकता है, या जो वर्तमान कैंसलेशन सीमा पर रोलबैक नहीं हो सकता है, उसे एक ड्यूरेबल क्यू या स्वतंत्र टास्क में ले जाएँ। इसे एक हैंडल, स्टेट स्टोर और आइडेम्पोटेंसी की के साथ मॉनिटर करें; सभी कैंसलेशन सेमेंटिक्स से बचने के लिए डिटैच्ड टास्क का उपयोग न करें।