𝗔 𝗦𝘂𝗰𝗰𝗲𝘀𝘀𝗳𝘂𝗹 𝗣𝗮𝘆𝗺𝗲𝗻𝘁 𝗧𝗵𝗮𝘁 𝗡𝗲𝘃𝗲𝗿 𝗕𝗲𝗰𝗮𝗺𝗲 𝗮 𝗕𝗼𝗼𝗸𝗶𝗻𝗴
एक ग्राहक ने भुगतान किया। Razorpay ने सफलता दिखाई। Webhook ने HTTP 200 भेजा। भुगतान कैप्चर (capture) कर लिया गया।
फिर भी बुकिंग "confirming" पर ही अटकी रही।
कोई एरर (error) नहीं आया। किसी भी एक्सेप्शन (exception) ने कोड को नहीं तोड़ा। कोई अलर्ट नहीं आया। हर मेट्रिक एक स्वस्थ सिस्टम दिखा रहे थे।
लेकिन ग्राहक के पास कुछ नहीं था। क्रिएटर के पास कोई बुकिंग नहीं थी।
पैसे स्वीकार करना आसान है। यह सुनिश्चित करना कि हर भुगतान एक बुकिंग में बदले, असली चुनौती है।
अधिकांश ट्यूटोरियल इस फ्लो (flow) का सुझाव देते हैं:
- Webhook इवेंट प्राप्त करता है
- Webhook बुकिंग अपडेट करता है
यह खतरनाक है। यदि बिजनेस लॉजिक (business logic) वेबहुक के अंदर ही रहता है, तो आप पूरी तरह से डिलीवरी की सफलता पर निर्भर होते हैं। Webhooks को रिट्राइज़ (retries), डुप्लिकेट्स और आंशिक विफलताओं (partial failures) का सामना करना पड़ता है।
हमने इन कार्यों को अलग करने के लिए अपने आर्किटेक्चर (architecture) को बदल दिया। अब Webhooks केवल इवेंट्स को रिकॉर्ड करते हैं। वे बिजनेस लॉजिक को निष्पादित नहीं करते हैं।
हमने तीन टेबल्स के साथ एक इवेंट लेजर (event ledger) पेश किया:
payment_orders: प्रोवाइडर की सच्चाई (provider truth)payment_events: अपरिवर्तनीय इवेंट लेजर (immutable event ledger)bookings: बिजनेस की सच्चाई (business truth)
अब Webhook का केवल एक काम है:
- सिग्नेचर (signature) सत्यापित करना
- इवेंट स्टोर करना
- 200 रिटर्न करना
यह सिस्टम की रक्षा करता है। यदि Webhook विफल हो जाता है, तो भी इवेंट सुरक्षित रहता है।
हमने यह भी सीखा कि पेमेंट स्टेट (payment state) और बुकिंग स्टेट (booking state) अलग-अलग होते हैं। एक कैप्चर किया गया भुगतान एक इनपुट है। एक कन्फर्म की गई बुकिंग परिणाम है। उन्हें अलग रखने से समाधान (reconciliation) संभव हो पाता है।
जांच के दौरान, हमें एक बग (bug) मिला। इवेंट्स डेटाबेस में मौजूद थे। प्रोसेसर स्वस्थ था। Webhook भी ठीक काम कर रहा था।
लेकिन प्रोसेसर कभी चला ही नहीं। लंबित (pending) इवेंट्स को प्रोसेस करने के लिए कोई भी फंक्शन को ट्रिगर नहीं कर रहा था।
इनजेशन (ingestion) को प्रोसेसिंग से अलग करना एक अच्छा डिज़ाइन है। लेकिन यह एक नई आवश्यकता पैदा करता है: कुछ ऐसा होना चाहिए जो प्रोसेसिंग को ट्रिगर करे।
हमने कई जॉब्स चलाने के लिए एक शेड्यूलर (scheduler) लागू किया:
- पेमेंट इवेंट्स को प्रोसेस करना
- छूटे हुए वेबहुक को रिकवर करना
- सिस्टम की निरंतरता (consistency) को सत्यापित करना
रिट्राइज़ के दौरान एरर से बचने के लिए, हम इस लॉजिक का उपयोग करते हैं:
- अनप्रोसेस्ड इवेंट्स को चुनें
- कई वर्कर्स को अनुमति देने के लिए
SKIP LOCKEDका उपयोग करें - सुनिश्चित करें कि डुप्लिकेट डिलीवरी से कुछ न हो
एक ऐसा सिस्टम जो केवल तभी काम करता है जब हर Webhook समय पर आए, एक नाजुक (fragile) सिस्टम है। यदि आपकी कतार (queue) को खाली करने वाला कोई नहीं है, तो काम हमेशा के लिए रुक जाएगा।
विश्वसनीयता का अर्थ है तब के लिए निर्माण करना जब चीजें विफल हो जाएं।