आइडेम्पोटेंसी क्या है, और डुप्लिकेट वेबहुक को कैसे संभालें?

आइडेम्पोटेंसी किसी दोहराए गए ऑपरेशन का असर एक ही ऑपरेशन जितना रखती है, इसलिए डुप्लिकेट वेबहुक को उनका काम दोहराए बिना संभालें।

कनेक्शन टूटने पर आपको पता नहीं चल पाता कि भेजने का अनुरोध सफल हुआ या नहीं। पुष्टि खो जाने पर वेबहुक भेजने वाला ऐसा इवेंट भी दोबारा डिलीवर कर सकता है जिसे आपका ऐप्लिकेशन पहले ही सहेज चुका है।

ये विफलताएँ विपरीत दिशाओं में होती हैं। Bird आपकी दी गई कुंजी से दोहराए गए API अनुरोध को पहचान सकता है। आपके webhook रिसीवर को स्वीकार किए गए इवेंट का अपना रिकॉर्ड रखना होता है।

मैं send को सुरक्षित रूप से फिर से प्रयास कैसे करूँ?

एक तार्किक API ऑपरेशन के हर प्रयास के लिए वही Idempotency-Key हेडर दोबारा इस्तेमाल करें।

कुंजी आप चुनते हैं, जो अधिकतम 255 अक्षरों की हो सकती है, और फिर से प्रयास करते समय उसे बनाए रखते हैं। welcome-user/usr_abc123 जैसा स्थिर मान आपकी प्रोसेस के दोबारा शुरू होने के बाद भी एक welcome-message ऑपरेशन की पहचान कर सकता है।

यह हेडर POST, PATCH और DELETE जैसे बदलाव करने वाले अनुरोधों पर लागू होता है। बिना कुंजी वाले अनुरोध को इस डुप्लिकेट-रोकथाम के बिना प्रोसेस किया जाता है। GET इस हेडर को अनदेखा करता है, क्योंकि रिसोर्स पढ़ना पहले से ही दोहराने के लिए सुरक्षित है।

मेल खाते पूरे हो चुके अनुरोध के लिए Bird संग्रहीत प्रतिक्रिया लौटाता है, जिसमें उसका मूल स्टेटस और बॉडी शामिल होते हैं। प्रतिक्रिया में Idempotency-Replay: true होता है, ताकि आप अपने लॉग में इस दोबारा उपयोग को पहचान सकें।

idempotency गाइड के अनुसार पूरी हो चुकी प्रतिक्रिया की अवधि डिफ़ॉल्ट रूप से तीन घंटे है। यह अवधि समाप्त होने के बाद किया गया फिर से प्रयास नए ऑपरेशन के रूप में चल सकता है। डुप्लिकेट send को हमेशा रोकने के लिए उस कुंजी पर निर्भर न रहें।

Bird SDK किसी बदलाव वाले अनुरोध के लिए कुंजी बनाते हैं और अपने आंतरिक फिर से प्रयासों में उसे दोबारा इस्तेमाल करते हैं। Bird CLI भी कुंजी न होने पर बदलाव वाले अनुरोध के लिए कुंजी बनाता है। जब अलग-अलग कमांड रन को एक ही ऑपरेशन साझा करना हो, तो --idempotency-key स्पष्ट रूप से सेट करें।

SMTP सबमिशन के लिए X-Bird-Idempotency-Key मैसेज हेडर इस्तेमाल करें। इससे फिर से प्रयास किया गया सबमिशन उसी ऑपरेशन की पहचान कर पाता है।

अगर मैं कुंजी गलत तरीके से दोबारा इस्तेमाल करूँ तो क्या होता है?

Bird किसी दूसरे ऑपरेशन की प्रतिक्रिया लौटाने के बजाय कुंजी के टकराव वाले उपयोग को अस्वीकार करता है।

स्थितिप्रतिक्रिया और समाधान
पूरा होने के बाद वही कुंजी और वही अनुरोधसंग्रहीत प्रतिक्रिया, Idempotency-Replay: true के साथ।
पूरी हो चुकी कुंजी किसी अलग अनुरोध के लिए दोबारा इस्तेमाल की गईE01005 के साथ 409, यानी idempotency कुंजी का दोबारा इस्तेमाल। फिर से प्रयास करने से पहले कुंजी ठीक करें।
उसी कुंजी वाला दूसरा अनुरोध अभी चल रहा हैE01004 के साथ 409, यानी अनुरोध प्रगति में है। थोड़ी देर रुकें और फिर से प्रयास करें।
कुंजी 255 अक्षरों से लंबी हैE01002 के साथ 400, यानी अमान्य इनपुट। कुंजी छोटी करें।

तुलना में मेथड, endpoint, path पैरामीटर, query string और body शामिल होते हैं। JSON के लिए whitespace बदलने से अनुरोध की पहचान बदल जाती है, इसलिए फिर से प्रयास करते समय मूल body को बिना बदले रखें।

अधूरे ऑपरेशन पर लगा लॉक तीस सेकंड के भीतर समाप्त हो जाता है। इस सीमा के कारण छोड़े गए ऑपरेशन के बाद कोई दूसरा अनुरोध आगे बढ़ सकता है। इससे यह तय नहीं होता कि कोई side effect पहले ही हो चुका है या नहीं।

Bird दोबारा लौटाने के लिए 5xx प्रतिक्रिया संग्रहीत नहीं करता। सर्वर त्रुटि या टाइमआउट होने पर उसी कुंजी से फिर से प्रयास करें, ताकि दर्ज की गई सफल प्रतिक्रिया फिर भी दोबारा इस्तेमाल हो सके।

सत्यापन या व्यावसायिक नियम के कारण अस्वीकृति होने पर कुंजी मुक्त हो जाती है। चूँकि कोई पूरी हुई प्रतिक्रिया सहेजी नहीं गई, आप उस अस्वीकृत अनुरोध को ठीक करके उसी कुंजी से फिर से प्रयास कर सकते हैं।

मुझे एक ही वेबहुक दो बार क्यों मिलता है?

अगर Bird को सफल प्रतिक्रिया नहीं मिलती, तो वह ऐसे इवेंट को फिर से भेजने का प्रयास कर सकता है जिसे आपका रिसीवर पहले ही सहेज चुका है।

रिसीवर कनेक्शन टूटने से ठीक पहले किसी इवेंट को सहेज सकता है। Bird को कोई सफल पावती नहीं दिखती, इसलिए वह फिर से प्रयास करता है, भले ही रिसीवर के पास इवेंट पहले से हो।

हर फिर से प्रयास में वही webhook-id हेडर रहता है, जो इवेंट की पहचान करता है। विफल डिलीवरी को दोबारा चलाने पर भी यही पहचानकर्ता रहता है, इसलिए दोनों को एक ही इवेंट के रूप में पहचाना जा सकता है।

मैं अपने हैंडलर को idempotent कैसे बनाऊँ?

इवेंट का काम शेड्यूल करने से पहले हर webhook-id को यूनिक डेटाबेस कंस्ट्रेंट के साथ सहेजें।

इन्सर्ट करने से पहले मौजूदा पंक्ति की जाँच करने पर रेस की स्थिति बनती है: दो समवर्ती अनुरोधों को एक साथ कोई पंक्ति न दिखे, ऐसा हो सकता है। डुप्लिकेट पहचानकर्ताओं को डेटाबेस से अस्वीकार करवाएँ।

पहचानकर्ता और जॉब को एक ही ट्रांज़ैक्शन में सहेजें। इससे ऐसा नहीं होगा कि पहचानकर्ता दर्ज हो जाए पर कोई काम कतार में न जुड़े।

  1. अनुरोध को सत्यापित करें, फिर उसके पहचानकर्ता और जॉब को एक ही ट्रांज़ैक्शन में इन्सर्ट करें।
  2. वह ट्रांज़ैक्शन कमिट होने के बाद 2xx लौटाएँ, ताकि Bird फिर से प्रयास करना बंद कर सके।
  3. सहेजे गए जॉब को ऐसे वर्कर में प्रोसेस करें जो अपनी कार्रवाइयों को सुरक्षित रूप से दोहरा सके।

यदि कोई डुप्लिकेट पहचानकर्ता पहले से कमिट हो चुका है, तो कोई नया जॉब बनाए बिना सफलता लौटाएँ। यदि ट्रांज़ैक्शन विफल हो जाए, तो त्रुटि लौटाएँ ताकि Bird फिर से प्रयास करे।

धीमे काम को रिसीवर से बाहर रखें, क्योंकि उसकी प्रतीक्षा करने से अनुरोध का टाइमआउट हो सकता है। वर्कर वेबहुक डिलीवरी से असंबंधित कारणों से भी फिर से प्रयास कर सकता है, इसलिए केवल रिसीवर को सुरक्षित करना पर्याप्त नहीं है।

इवेंट क्रम से बाहर भी पहुँच सकते हैं। नई स्थिति को ओवरराइट करने से पहले timestamp में इवेंट के समय की तुलना करें। विफल वेबहुक के फिर से प्रयास में आंशिक लागत वाला उदाहरण दिया गया है।

मुझे किन बातों पर निर्भर नहीं रहना चाहिए?

यह न मानें कि अनुरोधों के डुप्लिकेशन हटाने से डुप्लिकेट साइड इफ़ेक्ट असंभव हो जाते हैं।

यदि Bird का डुप्लिकेशन स्टोर उपलब्ध नहीं है, तो अनुरोध उसके बिना आगे बढ़ते हैं। जहाँ किसी कार्रवाई को दोहराना नुकसानदेह हो, वहाँ व्यावसायिक स्तर पर एक सुरक्षा उपाय रखें।

इसी तरह, webhook-id एक ही इवेंट की बार-बार होने वाली डिलीवरी को अलग पहचानता है। अलग-अलग इवेंट के पहचानकर्ता अलग होते हैं। इन इवेंट के लिए एक ही कार्रवाई दोहराना उचित है या नहीं, यह फिर भी आपका एप्लिकेशन तय करता है।

आइडेम्पोटेंसी में API के फिर से प्रयास का व्यवहार बताया गया है। वेबहुक में वे अलग डिलीवरी गारंटियाँ बताई गई हैं जिन्हें आपका रिसीवर संभालता है।

संक्षेप में

  1. API के लिए फिर से प्रयास और वेबहुक के फिर से प्रयास के लिए अलग-अलग रिकॉर्ड चाहिए।

    Bird को भेजे गए अनुरोध के लिए Idempotency-Key दोबारा इस्तेमाल करें। आपका रिसीवर webhook-id सहेजता है ताकि वह पहले से स्वीकार किए गए इवेंट को पहचान सके।

  2. अस्वीकार किए गए अनुरोध अपनी कुंजियाँ मुक्त कर सकते हैं।

    सत्यापन और बिज़नेस-नियम की त्रुटियों के बाद कोई पूरी प्रतिक्रिया सहेजी नहीं जाती, इसलिए आप अनुरोध सुधारकर उसी कुंजी से फिर से प्रयास कर सकते हैं।

  3. पूरी हो चुकी कुंजी अलग-अलग अनुरोधों की पहचान नहीं कर सकती।

    JSON का बॉडी या एंडपॉइंट बदलने पर 409 कॉन्फ़्लिक्ट मिल सकता है। उसी कॉन्फ़्लिक्ट के लिए बिना बदलाव फिर से प्रयास करने के बजाय कुंजी ठीक करें।

  4. डुप्लिकेशन रोकने की सीमाएँ हैं।

    अगर डुप्लिकेशन स्टोर उपलब्ध न हो, तो अनुरोध आगे बढ़ जाते हैं। अपने ऐप्लिकेशन में भी ऐसी व्यवस्था रखें कि दोहराई गई कार्रवाइयों से नुकसान न हो।

उसी नेटवर्क पर बनाएँ।

एक टेस्ट API key आपको तुरंत मिल जाती है। भुगतान विधि जोड़ने और सेंडर सत्यापित करने पर प्रोडक्शन अनलॉक होता है।

आपका अगला आइडिया। जुड़ने के लिए तैयार।