लंबे कार्यों के लिए इवेंट-ड्रिवन वर्कफ़्लो बनाम रिक्वेस्ट-रिस्पॉन्स API
लंबे चलने वाली प्रक्रियाओं के लिए इवेंट-ड्रिवन वर्कफ़्लो और रिक्वेस्ट-रिस्पॉन्स API की तुलना—व्यवसायिक ऐप में अनुमोदन, टाइमर, रिट्राइ और ऑडिट ट्रेल पर ध्यान।

क्यों व्यापार ऐप्स में लंबे चलने वाले प्रोसेस मुश्किल होते हैं
एक प्रक्रिया “लंबे चलने वाली” तब होती है जब वह एक त्वरित कदम में खत्म नहीं हो सकती। यह मिनट, घंटे, या दिन ले सकती है क्योंकि यह लोगों, समय, या बाहरी सिस्टम पर निर्भर करती है। अनुमोदन, हैंडऑफ और इंतज़ार वाली चीज़ें इसी श्रेणी में आती हैं।
यही वह जगह है जहाँ साधारण रिक्वेस्ट-रिस्पॉन्स API सोच टूटने लगती है। एक API कॉल शॉर्ट एक्सचेंज के लिए बनी होती है: एक अनुरोध भेजें, उत्तर पाएं, आगे बढ़ें। लंबे कार्य अधिक एक कहानी की तरह होते हैं जिसमें अध्याय होते हैं। आपको रुकना होता है, ठीक-ठीक याद रखना होता है कि आप कहाँ हैं, और बिना अनुमान लगाए बाद में जारी रखना होता है।
आप इसे रोज़मर्रा के बिजनेस ऐप्स में देखेंगे: ऐसा खरीद अनुमोदन जिसे मैनेजर और फाइनेंस दोनों चाहिए, कर्मचारी ऑनबोर्डिंग जो दस्तावेज़ जांच पर रुकी रहती है, रिफंड जो भुगतान प्रोवाइडर पर निर्भर होते हैं, या एक्सेस अनुरोध जिन्हें रिव्यू कर के लागू करना पड़ता है।
जब टीमें किसी लंबे प्रोसेस को एक ही API कॉल जैसा समझती हैं, तो कुछ अनुमानित समस्याएँ सामने आती हैं:
- एप्लिकेशन रिस्टार्ट या डिप्लॉय के बाद स्टेट खो देता है और भरोसेमंद तरीके से आगे नहीं बढ़ पाता।
- रिट्राइ डुप्लिकेट बनाते हैं: दूसरी भुगतान, दूसरी ईमेल, दोहरी स्वीकृति।
- मालिकाना अस्पष्ट हो जाता है: कोई नहीं जानता कि अगला कदम अनुरोधकर्ता, मैनेजर, या कोई सिस्टम जॉब कर रहा है।
- सपोर्ट के पास विजिबिलिटी नहीं होती और “यह कहाँ अटका है?” का जवाब देने के लिए लॉग्स खोदने पड़ते हैं।
- वेटिंग लॉजिक (टाइमर, रिमाइंडर, डेडलाइन) नाज़ुक बैकग्राउंड स्क्रिप्ट्स में बदल जाता है।
एक ठोस परिदृश्य: एक कर्मचारी सॉफ्टवेयर एक्सेस अनुरोध करता है। मैनेजर जल्दी से अप्रूव कर देता है, लेकिन IT को उसे प्रोविजन करने में दो दिन लगते हैं। अगर ऐप प्रोसेस स्टेट रखने, रिमाइंडर भेजने और सुरक्षित रूप से रीज़्यूम करने में असमर्थ है, तो आपको मैन्युअल फॉलो-अप, भ्रमित उपयोगकर्ता और अतिरिक्त काम मिलेगा।
यही वजह है कि लंबे चलने वाले बिजनेस प्रोसेस के लिए इवेंट-ड्रिवन वर्कफ़्लो बनाम रिक्वेस्ट-रिस्पॉन्स API का चुनाव सबसे ज़्यादा मायने रखता है।
दो मानसिक मॉडल: सिंक्रोनस कॉल बनाम समय पर इवेंट्स
सबसे सरल तुलना एक सवाल पर आती है: क्या काम वही समाप्त हो जाता है जब उपयोगकर्ता इंतज़ार कर रहा है, या क्या यह तब भी चलता रहता है जब वे जा चुके हों?
रिक्वेस्ट-रिस्पॉन्स API एक सिंगल एक्सचेंज है: एक कॉल इन, एक रिस्पॉन्स आउट। यह उन कार्यों के लिए फिट बैठता है जो जल्दी और अनुमानित तरीके से पूरे होते हैं, जैसे रिकॉर्ड बनाना, एक कोट कैलकुलेट करना, या इन्वेंटरी चेक करना। सर्वर काम करता है, सफलता या विफलता लौटाता है, और इंटरैक्शन खत्म हो जाता है।
इवेंट-ड्रिवन वर्कफ़्लो समय के साथ प्रतिक्रियाओं की एक श्रृंखला है। कुछ होता है (एक ऑर्डर बना, एक मैनेजर ने अनुमोदन दिया, एक टाइमर एक्सपायर हुआ), और वर्कफ़्लो अगले कदम पर जाता है। यह मॉडल उन कार्यों के लिए उपयुक्त है जिनमें हैंडऑफ, इंतज़ार, रिट्राइ और रिमाइंडर शामिल हों।
व्यावहारिक अंतर स्टेट में है।
रिक्वेस्ट-रिस्पॉन्स के साथ, स्टेट अक्सर वर्तमान अनुरोध और सर्वर मेमोरी में रहता है जब तक रिस्पॉन्स भेजा नहीं जाता। इवेंट-ड्रिवन वर्कफ़्लोज़ में स्टेट को संग्रहित करना पड़ता है (उदाहरण के लिए PostgreSQL में) ताकि प्रक्रिया बाद में फिर से शुरू हो सके।
फेलियर हैंडलिंग भी बदलती है। रिक्वेस्ट-रिस्पॉन्स आम तौर पर विफलताओं को ट्रैप करके एक एरर लौटाता है और क्लाइंट को फिर से प्रयास करने के लिए कहता है। वर्कफ़्लो विफलता को रिकॉर्ड करते हैं और परिस्थितियाँ सुधरने पर सुरक्षित रूप से पुनः प्रयास कर सकते हैं। वे हर स्टेप को एक इवेंट के रूप में लॉग भी कर सकते हैं, जिससे इतिहास को फिर से reconstruct करना आसान होता है।
एक सरल उदाहरण: “खर्च रिपोर्ट सबमिट करें” सिंक्रोनस हो सकती है। “अनुमोदन लो, 3 दिन इंतज़ार करो, मैनेजर को रिमाइंड करो, फिर भुगतान करो” नहीं है।
अनुमोदन: मानव निर्णयों को हर मॉडल कैसे हैंडल करता है
अनुमोदन वह जगह है जहाँ लंबे चलने वाला काम वास्तविक हो जाता है। एक सिस्टम स्टेप मिलीसेकंड में खत्म हो सकता है, पर इंसान दो मिनट या दो दिन में जवाब दे सकता है। मुख्य डिजाइन चुनाव यह है कि क्या आप उस इंतज़ार को एक रुकी हुई प्रक्रिया के रूप में मॉडल करेंगे, या बाद में आने वाले एक नए संदेश के रूप में।
रिक्वेस्ट-रिस्पॉन्स API के साथ, अनुमोदन अक्सर अजीब रूप ले लेते हैं:
- ब्लॉकिंग (व्यवहारिक नहीं)
- पोलिंग (क्लाइंट बार-बार पूछता है “क्या स्वीकृत हुआ?”)
- कॉलबैक्स/वेबहुक्स (सर्वर बाद में कॉल करता है)
ये सभी काम कर सकते हैं, पर मानव समय को API समय से जोड़ने के लिए अतिरिक्त प्लम्बिंग जोड़ते हैं।
इवेंट्स के साथ, अनुमोदन एक कहानी की तरह पढ़ता है। ऐप कुछ रिकॉर्ड करता है जैसे “ExpenseSubmitted,” फिर बाद में “ExpenseApproved” या “ExpenseRejected” आता है। वर्कफ़्लो इंजन (या आपका अपना स्टेट मशीन) केवल तब रिकॉर्ड को आगे बढ़ाता है जब अगला इवेंट आता है। यह कारोबार के कदमों के बारे में अधिकांश लोगों की सोच से मेल खाता है: सबमिट, समीक्षा, निर्णय।
जटिलता जल्दी से दिखाई देती है जब कई अनुमोदकों और एस्केलेशन नियमों की बात आती है। आप दोनों, मैनेजर और फाइनेंस की मंज़ूरी चाह सकते हैं, पर साथ ही एक सीनियर मैनेजर को ओवरराइड की अनुमति भी दे सकते हैं। अगर आप उन नियमों को स्पष्ट रूप से मॉडल नहीं करते, तो प्रक्रिया समझना मुश्किल और ऑडिट करना और भी कठिन हो जाएगा।
एक सरल अनुमोदन मॉडल जो स्केल करता है
एक व्यावहारिक पैटर्न यह है कि एक “अनुरोध” रिकॉर्ड रखें, फिर फैसलों को अलग से स्टोर करें। इस तरह आप कई अनुमोदकों का समर्थन कर सकते हैं बिना कोर लॉजिक को फिर से लिखे।
कुछ प्राथमिक डेटा को फ़र्स्ट‑क्लास रिकॉर्ड के रूप में कैप्चर करें:
- स्वयं अनुमोदन अनुरोध: क्या अनुमोदित होना है और उसका वर्तमान स्टेटस
- व्यक्तिगत निर्णय: किसने निर्णय लिया, approve/reject, टाइमस्टैम्प, कारण
- आवश्यक अनुमोदक: भूमिका या व्यक्ति, और कोई ऑर्डरिंग नियम
- परिणाम नियम: “कोई एक”, “बहुमत”, “सभी आवश्यक”, “ओवरराइड की अनुमति”
जो भी इम्प्लीमेंटेशन आप चुनें, हमेशा रिकॉर्ड करें कि किसने क्या कब और क्यों अनुमोदित किया—डेटा के रूप में, सिर्फ़ एक लॉग लाइन की तरह नहीं।
टाइमर और इंतज़ार: रिमाइंडर, डेडलाइन्स और एस्केलेशंस
इंतज़ार वह जगह है जहाँ लंबे टास्क गड़बड़ महसूस करने लगते हैं। लोग लंच पर जाते हैं, कैलेंडर भरे रहते हैं, और “हम आपको वापस सूचित करेंगे” दिखता‑सुनाई होकर “अब किसका यह है?” में बदल जाता है। यह इवेंट-ड्रिवन वर्कफ़्लो बनाम रिक्वेस्ट-रिस्पॉन्स API के बीच के सबसे साफ़ अंतर में से एक है।
रिक्वेस्ट-रिस्पॉन्स API के साथ, समय अजीब लगता है। HTTP कॉल्स की टाइमआउट होती है, इसलिए आप किसी अनुरोध को दो दिनों के लिए खुला नहीं रख सकते। टीमें आम तौर पर ऐसे पैटर्न अपना लेती हैं जैसे पोलिंग, एक अलग शेड्यूल्ड जॉब जो डेटाबेस स्कैन करता है, या ओवरड्यू चीज़ों के लिए मैन्युअल स्क्रिप्ट्स। ये काम कर सकते हैं, पर वेटिंग लॉजिक प्रोसेस के बाहर रहता है। कॉर्नर केस आसानी से छूट जाते हैं, जैसे जब जॉब दो बार चले, या रिकॉर्ड ठीक उस समय बदल गया जब रिमाइंडर भेजा जा रहा था।
वर्कफ़्लोज़ समय को एक सामान्य स्टेप की तरह मानते हैं। आप कह सकते हैं: 24 घंटे इंतज़ार करो, एक रिमाइंडर भेजो, फिर कुल 48 घंटे पर एस्केलेट कर दो। सिस्टम स्टेट रखता है, इसलिए डेडलाइन्स “cron + queries” प्रोजेक्ट में छुपे नहीं रहते।
एक सरल अनुमोदन नियम इस तरह दिख सकता है:
एक खर्च रिपोर्ट सबमिट होने के बाद 1 दिन इंतज़ार करें। अगर स्टेटस अभी भी “Pending” है, तो मैनेजर को संदेश भेजें। 2 दिन के बाद, अगर अभी भी पेंडिंग है, तो उसे मैनेजर के लीड को असाइन करें और एस्केलेशन रिकॉर्ड करें।
महत्वपूर्ण विवरण यह है कि जब टाइमर फ़ायर करे और दुनिया बदल चुकी हो तो आप क्या करते हैं। एक अच्छा वर्कफ़्लो हमेशा कार्रवाई करने से पहले वर्तमान स्टेट की फिर से जांच करता है:
- नवीनतम स्टेट लोड करें
- पुष्टि करें कि यह अभी भी पेंडिंग है
- पुष्टि करें कि असाइनी अभी भी वैध है (टीम में परिवर्तन होते हैं)
- आपने क्या फैसला किया और क्यों, उसे रिकॉर्ड करें
डुप्लिकेट कार्रवाई से बचते हुए रिट्राइ और फेलियर रिकवरी
रिट्राइ उन स्थितियों में आते हैं जब कुछ बाहरी कारणों से असफल हो गया: पेमेंट गेटवे टाइमआउट, ईमेल प्रोवाइडर अस्थायी त्रुटि लौटाता है, या आपकी ऐप स्टेप A सहेजती है पर क्रैश हो जाती है इससे पहले कि स्टेप B पूरा हो। खतरा सरल है: आप फिर से प्रयास करते हैं और गलती से वही कार्रवाई दो बार कर देते हैं।
रिक्वेस्ट-रिस्पॉन्स API के साथ, सामान्य पैटर्न यह है कि क्लाइंट एक एंडपॉइंट कॉल करता है, प्रतीक्षा करता है, और अगर स्पष्ट सफलता नहीं मिलती तो दोबारा कोशिश करता है। इसे सुरक्षित बनाने के लिए, सर्वर को बार‑बार कॉल्स को एक ही इरादे के रूप में ट्रीट करना चाहिए।
एक व्यावहारिक फिक्स है आइडेम्पोटेंसी की—क्लाइंट एक यूनिक टोकन भेजता है जैसे pay:invoice-583:attempt-1। सर्वर उस की के लिए परिणाम सहेजता है और रिपीट पर वही रिज़ल्ट लौटाता है। इससे डबल चार्ज, डुप्लिकेट टिकट या डुप्लिकेट अनुमोदन रोकता है।
इवेंट-ड्रिवन वर्कफ़्लोज़ में एक अलग तरह का डुप्लीकेशन रिस्क होता है। इवेंट अक्सर "at-least-once" डिलिवर होते हैं, जिसका मतलब है कि डुप्लीकेट्स दिखाई दे सकते हैं भले ही सब कुछ ठीक चल रहा हो। कंज्यूमर को डेडुप्लिकेशन की ज़रूरत होती है: इवेंट ID (या invoice_id + step जैसे बिजनेस की) रिकॉर्ड करें और रिपीट को अनदेखा करें। यह वर्कफ़्लो ऑर्केस्ट्रेशन पैटर्न का एक मूल अंतर है: रिक्वेस्ट-रिस्पॉन्स कॉल्स के सुरक्षित रीप्ले पर फोकस करता है, जबकि इवेंट्स मैसेजेस के सुरक्षित रीप्ले पर।
कुछ रिट्राइ नियम दोनों मॉडल में अच्छे काम करते हैं:
- बैकऑफ का उपयोग करें (उदाहरण: 10s, 30s, 2m).
- अधिकतम प्रयास सीमा सेट करें।
- अस्थायी त्रुटियों (रिट्राइ) और स्थायी त्रुटियों (तेज़ विफलता) को अलग करें।
- बार-बार विफलताओं को “needs attention” स्टेट में रूट करें।
- हर प्रयास को लॉग करें ताकि बाद में समझाया जा सके कि क्या हुआ।
रिट्राइ को प्रोसेस में स्पष्ट रखें, न कि छुपे हुए व्यवहार के रूप में। इस तरह आप विफलताओं को दृश्य और फिक्स करने योग्य बनाते हैं।
ऑडिट ट्रेल: प्रक्रिया को समझाने योग्य बनाना
एक ऑडिट ट्रेल आपकी "क्यों" फ़ाइल है। जब कोई पूछे, “यह खर्च क्यों अस्वीकार किया गया?” तो आपको माहों बाद भी अनुमान लगाए बिना उत्तर देना चाहिए। यह इवेंट-ड्रिवन वर्कफ़्लो और रिक्वेस्ट-रिस्पॉन्स दोनों में मायने रखता है, पर काम अलग दिखता है।
किसी भी लंबे चलने वाले प्रोसेस के लिए वे तथ्य रिकॉर्ड करें जो कहानी को रीप्ले करने दें:
- एक्टोर: किसने किया (यूज़र, सर्विस, या सिस्टम टाइमर)
- समय: कब हुआ (टाइम ज़ोन के साथ)
- इनपुट: उस समय क्या ज्ञात था (राशि, वेंडर, पॉलिसी थ्रेशहोल्ड, अनुमोदन)
- आउटपुट: क्या निर्णय या कार्रवाई हुई (approved, rejected, paid, retried)
- नियम वर्शन: किस पॉलिसी/लॉजिक वर्शन का उपयोग हुआ
इवेंट-ड्रिवन वर्कफ़्लोज़ ऑडिटिंग को आसान बना सकते हैं क्योंकि हर स्टेप स्वाभाविक रूप से ऐसा इवेंट पैदा करता है जैसे "ManagerApproved" या "PaymentFailed"। अगर आप उन इवेंट्स को पेलोड और एक्टोर के साथ स्टोर करते हैं, तो आपको एक साफ़ टाइमलाइन मिलती है। कुंजी यह है कि इवेंट्स वर्णनात्मक हों और उन्हें किसी जगह पर स्टोर करें जहाँ आप केस के हिसाब से क्वेरी कर सकें।
रिक्वेस्ट-रिस्पॉन्स API अभी भी ऑडिटेबल हो सकते हैं, पर कहानी अक्सर विभिन्न सेवाओं में बँटी हुई होती है। एक एंडपॉइंट “approved” लॉग करता है, दूसरा “payment requested” और तीसरा “retry succeeded”। अगर हर कोई अलग फ़ॉर्मेट या फ़ील्ड इस्तेमाल करे, तो ऑडिट डिटेक्टिव का काम बन जाता है।
एक सरल फिक्स है एक साझा “केस ID” (कॉरिलेशन ID भी कहा जाता है)। यह एक पहचान है जिसे आप हर अनुरोध, इवेंट और डेटाबेस रिकॉर्ड पर संलग्न करते हैं, जैसे “EXP-2026-00173।” फिर आप पूरे जर्नी को स्टेप्स में ट्रेस कर सकते हैं।
सही तरीका चुनना: ताकत और ट्रेड‑ऑफ़
सर्वश्रेष्ठ चुनाव इस पर निर्भर करता है कि आपको अभी उत्तर चाहिए, या आपको प्रक्रिया घंटों या दिनों तक आगे बढ़ाने की ज़रूरत है।
रिक्वेस्ट-रिस्पॉन्स तब अच्छा काम करता है जब काम छोटा हो और नियम सरल हों। उपयोगकर्ता एक फॉर्म सबमिट करता है, सर्वर उसे वैलिडेट करता है, डेटा सेव करता है और सफलता या त्रुटि लौटाता है। यह स्पष्ट, सिंगल‑स्टेप एक्शन्स जैसे create, update, या check permissions के लिए भी अच्छा है।
यह तब तक ठीक रहता है जब तक कि “सिंगल रिक्वेस्ट” चुपके से कई स्टेप में न बदल जाए: अनुमोदन का इंतज़ार, कई बाहरी सिस्टम कॉल, टाइमआउट्स, या अगले कदम के आधार पर ब्रांचिंग। आप या तो कनेक्शन खोल कर रखेंगे (नाज़ुक), या वेटिंग और रिट्राइज़ को ऐसे बैकग्राउंड जॉब्स में धकेल देंगे जिन्हें समझना मुश्किल होगा।
इवेंट-ड्रिवन वर्कफ़्लोज़ तब चमकते हैं जब प्रक्रिया समय के साथ एक कहानी है। हर स्टेप किसी नए इवेंट (approved, rejected, timer fired, payment failed) पर रिएक्ट करता है और तय करता है कि आगे क्या होगा। इससे रुकना, फिर से शुरु करना, रिट्राइ करना और निर्णय का स्पष्ट हिसाब रखना आसान हो जाता है।
असल ट्रेड‑ऑफ़्स हैं:
- सादगी बनाम टिकाऊपन: रिक्वेस्ट-रिस्पॉन्स शुरू करने में सरल है, इवेंट-ड्रिवन लंबे इंतज़ारों के लिए सुरक्षित है।
- डिबगिंग शैली: रिक्वेस्ट-रिस्पॉन्स सीधी रेखा का पालन करता है, वर्कफ़्लो अक्सर स्टेप्स के पार ट्रेसिंग मांगता है।
- टूलिंग और आदतें: इवेंट्स को अच्छे लॉगिंग, कॉरिलेशन IDs, और स्पष्ट स्टेट मॉडल चाहिए।
- परिवर्तन प्रबंधन: वर्कफ़्लोज़ विकसित और ब्रांच होते हैं; अगर सही तरह मॉडल किए गए हों तो इवेंट-ड्रिवन डिज़ाइन नए रास्तों को बेहतर संभालते हैं।
एक व्यावहारिक उदाहरण: एक खर्च रिपोर्ट जिसे पहले मैनेजर की मंजूरी चाहिए, फिर फाइनेंस समीक्षा, फिर भुगतान। अगर भुगतान विफल हो जाता है, तो आप डबल‑पेमेंट के बिना रिट्राइ चाहते हैं। यह स्वाभाविक रूप से इवेंट-ड्रिवन है। अगर यह सिर्फ़ “सबमिट खर्च” और जल्दी चेक्स हैं, तो रिक्वेस्ट-रिस्पॉन्स अक्सर काफी होता है।
कदम-दर-कदम: एक लंबी चलने वाली प्रक्रिया डिज़ाइन करना जो देरी को सह सके
लंबी चलने वाली बिजनेस प्रक्रियाएँ उबाऊ तरीकों से फेल होती हैं: ब्राउज़र टैब बंद हो जाता है, सर्वर रिस्टार्ट हो जाता है, एक अनुमोदन तीन दिन तक पेंडिंग रहता है, या पेमेंट प्रोवाइडर टाइमआउट कर देता है। किसी भी मॉडल को पसंद किए बिना शुरुआत से इन देरीयों के लिए डिज़ाइन करें।
एक छोटी सेट स्टेट्स को परिभाषित करें जिन्हें आप सहेज कर रीज़्यूम कर सकें। अगर आप अपने डेटाबेस में वर्तमान स्टेट की ओर इशारा नहीं कर सकते, तो आपका वर्कफ़्लो वास्तव में रीज़्यूमे योग्य नहीं है।
एक सरल डिज़ाइन अनुक्रम
- सीमाएँ तय करें: स्टार्ट ट्रिगर, एंड कंडीशन, और कुछ मुख्य स्टेट्स परिभाषित करें (Pending approval, Approved, Rejected, Expired, Completed)।
- इवेंट्स और निर्णय नामित करें: लिखें कि समय के साथ क्या‑क्या हो सकता है (Submitted, Approved, Rejected, TimerFired, RetryScheduled)। इवेंट नाम भूतकाल में रखें।
- वेटिंग पॉइंट चुनें: पहचानें कि प्रक्रिया कहाँ रुकेगी (मानव, बाहरी सिस्टम, या डेडलाइन के लिए)।
- प्रति स्टेप टाइमर और रिट्राइ नियम जोड़ें: तय करें कि समय बीतने पर या कॉल फेल होने पर क्या होगा (बैकऑफ, अधिकतम प्रयास, एस्केलेट, छोड़ देना)।
- परिभाषित करें कि प्रक्रिया कैसे रीज़्यूम करेगी: हर इवेंट या कॉलबैक पर, सहेजा हुआ स्टेट लोड करें, सत्यापित करें कि यह अभी भी वैध है, और फिर अगले स्टेट पर जाएँ।
रिस्टार्ट से बचने के लिए, वह न्यूनतम डेटा परिस्ट करें जिसकी आपको सुरक्षित जारी रखने के लिए ज़रूरत है। इतना स्टोर करें कि बिना अनुमान लगाए फिर से चलाया जा सके:
- प्रोसेस इंस्टेंस ID और वर्तमान स्टेट
- अगला कौन कार्रवाई कर सकता है (assignee/role) और उन्होंने क्या निर्णय लिया
- डेडलाइन्स (due_at, remind_at) और एस्केलेशन स्तर
- रिट्राइ मेटा (attempt count, last error, next_retry_at)
- साइड‑इफेक्ट्स के लिए आइडेम्पोटेंसी की या “पहले ही किया” फ्लैग
अगर आप स्टोर किए गए डेटा से "हम कहाँ हैं" और "अगला क्या अनुमत है" फिर से बना सकते हैं, तो देरी डरने वाली बात नहीं रहती।
सामान्य गलतियाँ और उन्हें कैसे टालें
लंबी प्रक्रियाएँ अक्सर तब टूटती हैं जब असली उपयोगकर्ता आ जाते हैं। एक अनुमोदन दो दिन लेता है, रिट्राइ गलत समय पर चलता है, और आपको डबल पेमेन्ट या गायब ऑडिट ट्रेल मिल जाता है।
आम गलतियाँ:
- मानव अनुमोदन का इंतज़ार करते हुए HTTP अनुरोध खुला रखना। यह टाइमआउट हो जाता है, सर्वर संसाधनों को बांधता है, और उपयोगकर्ता को गलत आभास देता है कि “कुछ हो रहा है।”
- आइडेम्पोटेंसी के बिना कॉल्स को रिट्राइ करना। नेटवर्क गल्ती डुप्लिकेट चालान, डुप्लीकेट ईमेल, या बार‑बार “Approved” ट्रांज़िशन बना सकती है।
- प्रोसेस स्टेट न स्टोर करना। अगर स्टेट मेमोरी में रहता है तो रिस्टार्ट उसे मिटा देता है। अगर स्टेट सिर्फ़ लॉग्स में है तो आप भरोसेमंद तरीके से जारी नहीं रख सकते।
- अस्पष्ट ऑडिट ट्रेल बनाना। इवेंट्स के अलग‑अलग क्लॉक और फ़ॉर्मैट होने से टाईमलाइन किसी घटना या अनुपालन समीक्षा के दौरान भरोसेमंद नहीं रहती।
- बिना एक स्रोत‑सत्य के असिंक और सिंक को मिला देना। एक सिस्टम कहता है “Paid,” दूसरा कहता है “Pending,” और कोई नहीं जानता कौन सही है।
एक सरल उदाहरण: खर्च रिपोर्ट चैट में मंज़ूर की जाती है, वेबहुक देर से आता है, और पेमेंट API रिट्राइ किया जाता है। स्टेट और आइडेम्पोटेंसी के बिना, रिट्राइ दो बार भुगतान भेज सकता है, और आपके रिकॉर्ड स्पष्ट रूप से यह बताने में विफल रहेंगे कि ऐसा क्यों हुआ।
अधिकांश फिक्स स्पष्ट होने में निहित हैं:
- स्टेट ट्रांज़िशन्स को डेटाबेस में पस्ट करें (Requested, Approved, Rejected, Paid) और किसने क्या बदला इसे रिकॉर्ड करें।
- प्रत्येक बाहरी साइड-इफेक्ट के लिए आइडेम्पोटेंसी कीज़ का उपयोग करें और उस की के लिए परिणाम स्टोर करें।
- “अनुरोध स्वीकार करें” और “काम पूरा करें” को अलग करें: तुरंत जवाब लौटाएँ, फिर बैकग्राउंड में वर्कफ़्लो पूरा करें।
- टाइमस्टैम्प्स को मानकीकृत करें (UTC), कॉरिलेशन IDs जोड़ें, और अनुरोध और परिणाम दोनों रिकॉर्ड करें।
बिल्ड करने से पहले त्वरित चेकलिस्ट
लंबा चलने वाला काम एक सही कॉल के बारे में नहीं, बल्कि देरी, लोग और विफलताओं के बाद भी सही बने रहने के बारे में है।
लिखें कि आपके प्रोसेस के लिए “सुरक्षित रूप से जारी रखना” का क्या अर्थ है। अगर ऐप बीच में रिस्टार्ट हो जाए, तो आपको आखिरी ज्ञात स्टेप से बिना अनुमान लगाए आगे बढ़ना चाहिए।
व्यवहारिक चेकलिस्ट:
- परिभाषित करें कि क्रैश या डिप्लॉय के बाद प्रक्रिया कैसे रीज़्यूम करेगी। कौन सा स्टेट सेव होता है, और अगला क्या चलेगा?
- हर इंस्टेंस को एक यूनिक प्रोसेस की दें (जैसे ExpenseRequest-10482) और एक स्पष्ट स्टेटस मॉडल (Submitted, Waiting for Manager, Approved, Paid, Failed)।
- अनुमोदनों को केवल परिणाम न मानें, उन्हें रिकॉर्ड करें: किसने अनुमोदन/अस्वीकृति किया, कब, और कारण या टिप्पणी क्या थी।
- वेटिंग नियमों का नक्शा बनाएं: रिमाइंडर, डेडलाइन्स, एस्केलेशंस, एक्सपाइरिज़। हर टाइमर के लिए एक मालिक नामित करें (मैनेजर, फाइनेंस, सिस्टम)।
- विफलता हैंडलिंग प्लान करें: रिट्राइ सीमित और सुरक्षित होने चाहिए, और एक “needs review” स्टॉप होना चाहिए जहाँ इंसान डेटा ठीक कर सके या पुनः प्रयास की अनुमति दे सके।
सैनिटी टेस्ट: कल्पना करें कि आपने कार्ड चार्ज कर दिया पर भुगतान प्रदाता टाइमआउट कर देता है। आपका डिज़ाइन डबल चार्ज को रोकते हुए प्रोसेस पूरा करने दे सकता है?
उदाहरण: डेडलाइन और पेमेंट रिट्राइ के साथ खर्च अनुमोदन
परिदृश्य: एक कर्मचारी एक $120 टैक्सी रसीद सबमिट करता है। इसे 48 घंटे के भीतर मैनेजर की मंज़ूरी चाहिए। मंज़ूरी मिलने पर सिस्टम कर्मचारी को भुगतान करता है। अगर भुगतान विफल होता है, तो यह सुरक्षित रूप से रिट्राइ करता है और एक स्पष्ट रिकॉर्ड छोड़ता है।
रिक्वेस्ट-रिस्पॉन्स वॉकथ्रू
रिक्वेस्ट-रिस्पॉन्स API के साथ, ऐप अक्सर उस बातचीत जैसा होता है जिसे बार-बार चेक करना पड़ता है।
कर्मचारी Submit दबाता है। सर्वर एक reimbursement रिकॉर्ड बनाता है जिसका स्टेट “Pending approval” होता है और एक ID लौटाता है। मैनेजर को नोटिफिकेशन मिलता है, पर कर्मचारी ऐप को आम तौर पर यह देखने के लिए पोलिंग करनी पड़ती है कि कुछ बदला है या नहीं, उदाहरण: “GET reimbursement status by ID.”
48 घंटे की डेडलाइन लागू करने के लिए, आप या तो एक शेड्यूल्ड जॉब चलाते हैं जो ओवरड्यू रिक्वेस्ट्स स्कैन करता है, या आप एक डेडलाइन टाइमस्टैम्प स्टोर करते हैं और पोल्स के दौरान इसकी जांच करते हैं। अगर जॉब लेट होता है, तो उपयोगकर्ता स्टेटस पुराने देख सकते हैं।
जब मैनेजर अप्रूव करता है, सर्वर स्टेट को “Approved” में बदलता है और पेमेंट प्रोवाइडर को कॉल करता है। अगर Stripe अस्थायी त्रुटि लौटाता है, तो सर्वर को यह तय करना होगा कि अभी रिट्राइ करें, बाद में रिट्राइ शेड्यूल करें, या फेल कर दें। सावधानीपूर्वक आइडेम्पोटेंसी कीज़ के बिना, रिट्राइ डबल पेआउट बना सकती है।
इवेंट-ड्रिवन वॉकथ्रू
इवेंट-ड्रिवन मॉडल में, हर परिवर्तन एक रिकॉर्डेड तथ्य होता है।
कर्मचारी सबमिट करता है, जिससे एक “ExpenseSubmitted” इवेंट बनता है। एक वर्कफ़्लो शुरू होता है और या तो “ManagerApproved” या 48 घंटे पर “DeadlineReached” टाइमर इवेंट का इंतज़ार करता है। अगर टाइमर पहले फायर करता है, वर्कफ़्लो “AutoRejected” और कारण रिकॉर्ड करता है।
अनुमोदन पर, वर्कफ़्लो “PayoutRequested” रिकॉर्ड करता है और भुगतान का प्रयास करता है। अगर Stripe टाइमआउट करता है, तो यह “PayoutFailed” को एक एरर कोड के साथ रिकॉर्ड करता है, 15 मिनट में रिट्राइ शेड्यूल करता है, और आइडेम्पोटेंसी की की मदद से तभी “PayoutSucceeded” रिकॉर्ड करता है जब भुगतान वाकई सफल हो।
उपयोगकर्ता के लिए दिखने वाली चीज़ें सरल रहती हैं:
- Pending approval (बचे हुए 48 घंटे)
- Approved, भुगतान किया जा रहा है
- भुगतान रिट्राइ शेड्यूल किया गया
- भुगतान हो गया
ऑडिट ट्रेल टाइमलाइन की तरह पढ़ती है: submitted, approved, deadline checked, payout attempted, failed, retried, paid.
अगले कदम: मॉडल को काम करने वाले ऐप में बदलना
एक असली प्रोसेस चुनें और उसे end-to-end बनाकर दिखाएँ इससे पहले कि आप सामान्यीकृत करें। खर्च अनुमोदन, ऑनबोर्डिंग और रिफंड हैंडलिंग अच्छी शुरुआत हैं क्योंकि इनमें मानव स्टेप्स, वेटिंग और फेलियर पाथ शामिल होते हैं। लक्ष्य छोटा रखें: एक हैप्पी पाथ और दो सबसे सामान्य अपवाद।
प्रोसेस को स्क्रीन के रूप में नहीं बल्कि स्टेट्स और इवेंट्स के रूप में लिखें। उदाहरण: “Submitted” -> “ManagerApproved” -> “PaymentRequested” -> “Paid,” शाखाएँ जैसे “ApprovalRejected” या “PaymentFailed।” जब आप वेटिंग पॉइंट्स और साइड-इफेक्ट्स को स्पष्ट देखें, तो इवेंट-ड्रिवन वर्कफ़्लो बनाम रिक्वेस्ट-रिस्पॉन्स API का चुनाव व्यावहारिक हो जाएगा।
निर्णय लें कि प्रोसेस स्टेट कहाँ रहता है। अगर फ्लो सरल है और आप एक जगह अपडेट को लागू कर सकते हैं तो डेटाबेस काफी हो सकता है। जब आपको टाइमर, रिट्राइ और ब्रांचिंग चाहिए तो एक वर्कफ़्लो इंजन मदद करता है क्योंकि वह अगले क्या होना चाहिए, इसे ट्रैक करता है।
शुरू से ही ऑडिट फ़ील्ड जोड़ें। किसने क्या किया, कब हुआ, और क्यों (कमेंट या कारण कोड) स्टोर करें। जब कोई पूछे, “यह भुगतान क्यों रिट्राइ किया गया?” तब आप बिना लॉग्स खोदने स्पष्ट उत्तर देना चाहते हैं।
अगर आप इस तरह का वर्कफ़्लो किसी नो‑कोड प्लेटफ़ॉर्म में बना रहे हैं, तो AppMaster (appmaster.io) एक विकल्प है जहाँ आप PostgreSQL में डेटा मॉडल कर सकते हैं और विज़ुअल तरीके से प्रोसेस लॉजिक बना सकते हैं, जिससे वेब और मोबाइल ऐप्स में अनुमोदन और ऑडिट ट्रेल्स कंसिस्टेंट रखना आसान होता है।
सामान्य प्रश्न
यदि काम जल्दी और अनुमानित तरीके से पूरा हो जाता है जबकि उपयोगकर्ता इंतज़ार कर रहा है — जैसे रिकॉर्ड बनाना या फ़ॉर्म सत्यापित करना — तो request-response का उपयोग करें। अगर प्रक्रिया मिनटों से लेकर दिनों तक फैलती है, मानव अनुमोदन शामिल हैं, या टाइमर, रिट्राइ और सुरक्षित रीज़्यूम की ज़रूरत है, तो इवेंट-ड्रिवन वर्कफ़्लो बेहतर है।
लंबे कार्य एक ही HTTP अनुरोध में फिट नहीं बैठते क्योंकि कनेक्शन्स टाइम आउट हो जाते हैं, सर्वर रिस्टार्ट हो सकते हैं, और काम अक्सर लोगों या बाहरी सिस्टम पर निर्भर होता है। एक ही कॉल की तरह ट्रीट करने पर आप अक्सर स्टेट खो देते हैं, रिट्राइ पर डुप्लीकेट बन जाते हैं, और वेटिंग हैंडल करने के लिए विखंडित बैकग्राउंड स्क्रिप्ट्स बन जाती हैं।
एक अच्छा डिफ़ॉल्ट यह है कि स्पष्ट प्रोसेस स्टेट को अपने डेटाबेस में सहेजा जाए और इसे केवल स्पष्ट ट्रांज़िशन्स के माध्यम से आगे बढ़ाया जाए। प्रोसेस इंस्टेंस ID, वर्तमान स्टेटस, अगला कौन कार्रवाई कर सकता है, और प्रमुख टाइमस्टैम्प्स स्टोर करें ताकि डिप्लॉय, क्रैश या देरी के बाद सुरक्षित रूप से रीज़्यूम किया जा सके।
ब्लॉक करने या लगातार पोलिंग के बजाय अनुमोदनों को एक रुके हुए स्टेप के रूप में मॉडल करें जो निर्णय आने पर फिर से चल पड़े। हर निर्णय को डेटा के रूप में रिकॉर्ड करें (किसने निर्णय लिया, कब, स्वीकृति/अस्वीकृति, और कारण) ताकि वर्कफ़्लो अनुमानित रूप से आगे बढ़ सके और बाद में ऑडिट किया जा सके।
सरल मामलों में पोलिंग काम कर सकती है, पर यह शोर और देरी बढ़ाती है क्योंकि क्लाइंट बार-बार पूछता रहता है “क्या यह हो गया?” बेहतर तरीका है कि बदलाव होने पर नोटिफिकेशन पुश करें और क्लाइंट आवश्यकतानुसार रिफ्रेश करे, जबकि सर्वर स्टेट का स्रोत बना रहे।
समय को प्रोसेस का हिस्सा मानें: डेडलाइन्स और रिमाइंडर टाइम स्टोर करें, और जब टाइमर फ़ायर करे तब वर्तमान स्टेट को फिर से जांचकर कार्रवाई करें। इससे चीज़ें तब नहीं चलतीं जब कुछ पहले ही स्वीकृत हो गया हो, और एस्केलेशन भी तब तक लगातार रहता है भले ही जॉब लेट या दोगुना चले।
हर बाहरी साइड-इफेक्ट के लिए आइडेम्पोटेंसी कीज़ का उपयोग करें — जैसे कार्ड चार्ज करना या ईमेल भेजना — और उस की के लिए परिणाम सहेजें। फिर रिट्राइ सुरक्षित हो जाते हैं क्योंकि एक ही इरादा दोहराने पर वही परिणाम लौटेगा, न कि कार्रवाई दुहराई जाएगी।
मैसेज डिलिवरी को अधिक-से-अधिक-एक बार मानें और उपभोक्ताओं को डुप्लिकेट हटाने के लिए बनाएं। व्यवहारिक तरीका है कि आप इवेंट ID (या उस स्टेप के लिए कोई बिजनेस की) स्टोर करें और रिपीट को नजरअंदाज करें, ताकि रिप्ले उसी एक्शन को दोबारा ट्रिगर न करे।
एक टाइमलाइन फ़ैक्ट्स की कैप्चर करें: अभिनेता (actor), टाइमस्टैम्प, उस समय उपलब्ध इनपुट, आउटपुट/नतीजा, और उपयोग किए गए नियम या पॉलिसी वर्शन। साथ ही हर प्रोसेस से संबंधित चीज़ों पर एक सिंगल केस या कॉरिलेशन ID लगाएँ ताकि सपोर्ट बिना असंबंधित लॉग्स खंगाले यह बता सके कि “यह कहाँ अटका है?”
एक अनुरोध रिकॉर्ड को ‘केस’ के रूप में रखें, निर्णयों को अलग स्टोर करें, और स्टेट परिवर्तन को सहेजे गए ट्रांज़िशन्स के माध्यम से चलाएं ताकि उन्हें फिर से चलाया जा सके। नो-कोड टूल में (जैसे AppMaster) आप PostgreSQL में डेटा मॉडल कर सकते हैं और स्टेप लॉजिक विज़ुअली लागू कर सकते हैं, जिससे अनुमोदन, रिट्राइ और ऑडिट फ़ील्ड्स पूरे ऐप में सुसंगत रहते हैं।


