प्रगति अपडेट वाले पृष्ठभूमि कार्य: प्रभावी UI पैटर्न
प्रगति अपडेट वाले पृष्ठभूमि कार्यों के व्यवहारिक पैटर्न सीखें — क्यूज़, स्टेट मॉडल, UI मैसेजिंग, कैंसल/रीट्राई, और एरर रिपोर्टिंग सहित।

क्यों उपयोगकर्ता पृष्ठभूमि में चलने वाले कार्यों में अटके रहते हैं
लंबी कार्रवाई UI को ब्लॉक नहीं करनी चाहिए। लोग टैब बदल देते हैं, कनेक्शन खो देते हैं, लैपटॉप बंद कर देते हैं, या बस सोचते हैं कि क्या कुछ हो रहा है। जब स्क्रीन फ्रीज़ दिखती है तो उपयोगकर्ता अनुमान लगाते हैं, और अनुमान बार-बार क्लिक, डुप्लिकेट सबमिशन और सपोर्ट टिकट में बदल जाता है.
अच्छा बैकग्राउंड वर्क असल में भरोसे के बारे में है। उपयोगकर्ता तीन चीज़ें चाहते हैं:
- एक स्पष्ट स्थिति (queued, running, done)
- समय का अंदाज़ (यहाँ तक कि एक मोटा अनुमान भी)
- एक स्पष्ट अगला कदम (इंतजार करें, काम जारी रखें, कैंसल करें, या बाद में लौटें)
इनके बिना, जॉब सही चल रहा हो सकता है, पर अनुभव टूटा हुआ लगेगा।
एक आम भ्रम यह है कि धीरे चलने वाले रिक्वेस्ट को असली बैकग्राउंड वर्क समझ लिया जाए। एक स्लो रिक्वेस्ट अभी भी एक वेब कॉल है जो उपयोगकर्ता को इंतजार करवाती है। बैकग्राउंड वर्क अलग है: आप एक जॉब शुरुआत करते हैं, तुरंत पुष्टिकरण मिलता है, और भारी प्रोसेसिंग कहीं और होती है जबकि UI इस्तेमाल करने योग्य रहता है।
उदाहरण: उपयोगकर्ता ग्राहक इम्पोर्ट करने के लिए CSV अपलोड करता है। अगर UI ब्लॉक हो जाए तो वे रिफ्रेश कर सकते हैं, फिर से अपलोड कर सकते हैं और डुप्लिकेट बना सकते हैं। अगर इम्पोर्ट बैकग्राउंड में शुरू हो और UI एक जॉब कार्ड प्रगति और एक सुरक्षित Cancel विकल्प दिखाए, तो वे काम जारी रख सकते हैं और स्पष्ट नतीजे पर वापस आ सकते हैं।
मूल बिल्डिंग ब्लॉक्स: जॉब, क्यू, वर्कर और स्टेटस
जब लोग प्रगति अपडेट वाले बैकग्राउंड टास्क की बात करते हैं, तो आमतौर पर चार हिस्से मिलकर काम करते हैं।
एक जॉब काम की इकाई है: "इस CSV को इम्पोर्ट करो", "यह रिपोर्ट जेनरेट करो", या "5,000 ईमेल भेजो"। एक क्यू वह लाइन है जहाँ जॉब वेट करता है जब तक उसे प्रोसेस किया नहीं जा सकता। एक वर्कर क्यू से जॉब लेता है और काम करता है (एक-एक करके या पैरेलल में)।
UI के लिए सबसे महत्वपूर्ण हिस्सा जॉब की लाइफ़साइकल स्टेट है। स्टेट्स को कम और प्रेडिक्टेबल रखें:
- Queued: स्वीकार किया गया, वर्कर का इंतजार
- Running: सक्रिय रूप से प्रोसेस कर रहा है
- Done: सफलतापूर्वक पूरा हुआ
- Failed: एरर के साथ रुका
हर जॉब को एक जॉब ID चाहिए (एक यूनिक रेफरेंस)। जब उपयोगकर्ता बटन क्लिक करे, उस ID को तुरंत लौटाएँ और टास्क पैनल में "Task started" जैसा एक रो दिखाएँ।
फिर आपको यह पूछने का तरीका चाहिए, "अब क्या हो रहा है?"। यह आमतौर पर एक स्टेटस एंडपॉइंट (या कोई भी रीड मेथड) होता है जो जॉब ID लेता है और स्टेट के साथ प्रोग्रेस डिटेल्स लौटाता है। UI इसे प्रतिशत पूरा हुआ, करंट स्टेप और कोई मैसेज दिखाने के लिए इस्तेमाल करता है।
अंत में, स्टेटस को ड्यूरेबल स्टोर में रहना चाहिए, केवल मेमोरी में नहीं। वर्कर क्रैश होते हैं, ऐप रिस्टार्ट होते हैं, और उपयोगकर्ता पेज रिफ्रेश करते हैं। ड्यूरेबल स्टोरेज वही चीज़ है जो प्रगति और नतीजों को विश्वसनीय बनाती है। कम से कम स्टोर करें:
- करंट स्टेट और टाइमस्टैम्प
- प्रोग्रेस वैल्यू (प्रतिशत या काउंट)
- रिज़ल्ट समरी (क्या बनाया या बदला गया)
- एरर डिटेल्स (डिबग और यूज़र-फ्रेंडली मैसेज)
अगर आप AppMaster जैसे प्लेटफ़ॉर्म में बना रहे हैं, तो स्टेटस स्टोर को किसी अन्य डेटा मॉडल की तरह मानें: UI जॉब ID से पढ़ता है, और वर्कर जॉब चलते हुए इसे अपडेट करता है।
अपने वर्कलोड के अनुकूल क्यू पैटर्न चुनना
आप जो क्यू पैटर्न चुनते हैं वह यह बदल देता है कि आपका ऐप कितना "फेयर" और प्रेडिक्टेबल लगेगा। अगर एक टास्क बहुत सारे अन्य वर्क के पीछे बैठा है, तो उपयोगकर्ता उसे यादृच्छिक देरी के रूप में अनुभव करेंगे, भले ही सिस्टम स्वस्थ हो। इसलिए क्यू का चुनाव UX का निर्णय भी है, सिर्फ़ इन्फ्रास्ट्रक्चर का नहीं।
जब वॉल्यूम कम हो, जॉब छोटे हों, और आप कभी-कभी retries सहन कर सकते हों तो सादा डेटाबेस-आधारित क्यू अक्सर पर्याप्त होता है। इसे सेटअप करना आसान है, निरीक्षण आसान है, और आप सब कुछ एक जगह रख सकते हैं। उदाहरण: एक एडमिन रात में एक छोटी टीम के लिए रिपोर्ट चलाता है। अगर यह एक बार retry हो जाए तो कोई घबराता नहीं।
जब थ्रूपुट बढ़े, जॉब भारी हो जाएँ, या विश्वसनीयता अनिवार्य हो जाए तो समर्पित क्यू सिस्टम चाहिए। इम्पोर्ट, वीडियो प्रोसेसिंग, मास नोटिफिकेशन और किसी भी वर्कफ़्लो जो रिस्टार्ट्स पार कर के चलनी चाहिए, बेहतर आइसोलेशन, दृश्यता और सुरक्षित retry व्यवहार से लाभ पाते हैं। यह उपयोगकर्ता-फेसिंग प्रोग्रेस के लिए मायने रखता है क्योंकि लोग गायब अपडेट और अटके स्टेट नोटिस करते हैं।
क्यू संरचना प्रायरिटी को भी प्रभावित करती है। एक ही क्यू सरल है, पर तेज़ और धीमा वर्क मिलाने से तेज़ क्रियाएँ धीमी लग सकती हैं। अलग क्यू मदद करते हैं जब आपके पास यूजर-ट्रिगर किया गया वर्क है जिसे तुरंत महसूस कराना है और साथ ही शेड्यूल्ड बैच वर्क जो बाद में हो सकता है।
कनकरेंसी लिमिट्स जानबूझकर सेट करें। बहुत ज्यादा पैरेललिज़्म आपका डेटाबेस ओवरलोड कर सकता है और प्रोग्रेस कूदती हुई लग सकती है। बहुत कम होने पर सिस्टम सुस्त लगेगा। हर क्यू पर छोटे, प्रेडिक्टेबल concurrency से शुरू करें और तभी बढ़ाएँ जब पूरा होने का समय स्थिर रखा जा सके।
UI में दिखाने लायक प्रोग्रेस मॉडल डिज़ाइन करना
अगर आपका प्रोग्रेस मॉडल अस्पष्ट है तो UI भी अस्पष्ट लगेगा। तय करें कि सिस्टम क्या ईमानदारी से रिपोर्ट कर सकता है, कितनी बार बदलता है, और उपयोगकर्ता इस जानकारी के साथ क्या करें।
एक सरल स्टेटस स्कीमा जो अधिकतर जॉब्स सपोर्ट कर सकते हैं इस तरह दिखता है:
- state: queued, running, succeeded, failed, canceled
- percent: 0-100 जब आप माप सकते हों
- message: एक छोटी सेंटेंस जो उपयोगकर्ता समझे
- timestamps: created, started, last_updated, finished
- result_summary: प्रोसेस्ड, स्किप्ड, errors जैसे काउंट
अगला, परिभाषित करें कि "प्रोग्रेस" का मतलब क्या है।
प्रतिशत तब काम करता है जब असली डिनॉमिनेटर हो (फाइल की पंक्तियाँ, भेजे जाने वाले ईमेल)। जब काम अनिर्वचनीय हो (तीसरे पक्ष का इंतजार, बदलते कंप्यूट, महंगे क्वेरी) तो प्रतिशत भ्रामक होता है। ऐसे मामलों में स्टेप-आधारित प्रोग्रेस भरोसा बनाता है क्योंकि यह स्पष्ट खंडों में आगे बढ़ता है।
एक प्रैक्टिकल नियम:
- तब percent का उपयोग करें जब आप रिपोर्ट कर सकें "X of Y"।
- जब अवधि अज्ञात हो तो steps का इस्तेमाल करें (Validate file, Import, Rebuild indexes, Finalize)।
- जब दोनों न हों तो indeterminate प्रोग्रेस रखें, पर मैसेज ताज़ा रखें।
जॉब चलते समय आंशिक परिणाम स्टोर करें। इससे UI जॉब खत्म होने से पहले कुछ उपयोगी दिखा सकेगा, जैसे लाइव एरर काउंट या बदलियों का प्रीव्यू। CSV इम्पोर्ट के लिए, आप rows_read, rows_created, rows_updated, rows_rejected और आखिरी कुछ एरर मैसेज स्टोर कर सकते हैं।
यह भरोसेमंद बैकग्राउंड टास्क का आधार है: UI शांत रहता है, नंबर्स चलते रहते हैं, और "क्या हुआ?" का सारांश जॉब खत्म होते ही तैयार रहता है।
प्रोग्रेस अपडेट डिलीवरी: polling, push और हाइब्रिड
बैकएंड से स्क्रीन तक प्रोग्रेस पहुँचाना वो जगह है जहाँ कई इम्प्लीमेंटेशन विफल होते हैं। ऐसा डिलीवरी तरीका चुनें जो इस बात से मेल खाए कि प्रोग्रेस कितनी बार बदलती है और कितने उपयोगकर्ता इसे देख रहे होंगे।
Polling सबसे सरल है: UI हर N सेकंड में स्टेट पूछता है। एक अच्छा डिफ़ॉल्ट सक्रिय देखने पर 2 से 5 सेकंड है, फिर समय के साथ बैक ऑफ करें। अगर टास्क एक मिनट से अधिक चलता है तो 10–30 सेकंड पर जाएँ। अगर टैब बैकग्राउंड में है तो और धीमा करें।
Push अपडेट (WebSockets, server-sent events, या मोबाइल नोटिफिकेशन) तब मदद करते हैं जब प्रोग्रेस जल्दी बदलती है या उपयोगकर्ताओं को "अभी" की जानकारी चाहिए। Push तुरंतपन देता है, पर कनेक्शन ड्रॉप होने पर fallback अभी भी जरूरी है।
एक हाइब्रिड अप्रोच अक्सर सबसे बेहतर है: शुरुआत में तेज़ पोलिंग करें (ताकि UI जल्दी देखे queued से running होना), फिर जॉब स्थिर होने पर धीमा कर दें। यदि आप push जोड़ते हैं तो safety के लिए धीमा पोल रखें।
जब अपडेट्स रुक जाएँ तो इसे एक प्रथम श्रेणी स्टेट समझें। दिखाएँ "Last updated 2 minutes ago" और रिफ्रेश का विकल्प दें। बैकएंड पर, heartbeat नहीं मिलने पर जॉब को stale मार्क करें।
लंबे समय तक चलने वाले टास्क के लिए UI पैटर्न जो स्पष्ट लगें
स्पष्टता दो चीज़ों से आती है: कुछ ही प्रेडिक्टेबल स्टेट्स, और ऐसी कॉपी जो बताती है कि आगे क्या होगा।
UI में स्टेट्स का नाम दें, सिर्फ़ बैकएंड में नहीं। एक जॉब queued हो सकता है (अपनी बारी का इंतजार), running (काम कर रहा), waiting for input (किसी विकल्प की ज़रूरत), completed, completed with errors, या failed। अगर उपयोगकर्ता इन्हें अलग नहीं कर पाते तो वे समझेंगे कि ऐप अटकी हुई है।
प्रोग्रेस इंडिकेटर के पास सधा हुआ, उपयोगी टेक्स्ट रखें। "Importing 3,200 rows (1,140 processed)", सिर्फ़ "Processing" से बेहतर है। एक वाक्य जोड़ें जो जवाब दे: क्या मैं छोड़ सकता हूँ, और क्या होगा? उदाहरण: "आप यह विंडो बंद कर सकते हैं। हम बैकग्राउंड में इम्पोर्ट जारी रखेंगे और तैयार होने पर आपको सूचित करेंगे।"
प्रोग्रेस कहाँ दिखे यह उपयोगकर्ता के संदर्भ से मेल खाना चाहिए:
- जब टास्क अगले कदम को ब्लॉक करता है (उदाहरण के लिए तुरंत एक invoice PDF जनरेट करना), तो एक modal काम आता है।
- त्वरित टास्क के लिए जो बाधा नहीं डालने चाहिए, एक toast अच्छा है।
- प्रति-आइटम ऑपरेशनों के लिए टेबल रो में inline प्रोग्रेस काम करता है।
एक मिनट से लंबी किसी भी चीज़ के लिए एक साधारण Jobs पेज (या Activity पैनल) जोड़ें ताकि लोग बाद में काम ढूँढ सकें।
एक स्पष्ट लॉन्ग-रनिंग टास्क UI आमतौर पर शामिल करता है: एक स्टेटस लेबल साथ में last updated समय, एक प्रोग्रेस बार (या स्टेप्स) एक लाइन में विवरण, सुरक्षित Cancel बिहेवियर, और एक रिज़ल्ट एरिया जिसमें समरी और अगला कदम हो। पूर्ण जॉब्स को खोजनीय रखें ताकि उपयोगकर्ताओं को एक स्क्रीन पर फंसा न रखें।
"Finished with errors" को उपयोगकर्ताओं के लिए उलझन मुक्त रिपोर्ट करना
"Finished" हमेशा जीत नहीं है। जब बैकग्राउंड जॉब 9,500 रिकॉर्ड प्रोसेस करे और 120 फेल हों, तो उपयोगकर्ता को बिना लॉग पढ़े समझ में आना चाहिए कि क्या हुआ।
आंशिक सफलता को एक मान्य परिणाम मानें। मुख्य स्टेट लाइन में दोनों पक्ष दिखाएँ: "Imported 9,380 of 9,500. 120 failed." यह भरोसा बनाए रखता है क्योंकि सिस्टम ईमानदार है और पुष्टि करता है कि काम सेव हुआ।
फिर एक छोटा एरर समरी दिखाएँ जिस पर उपयोगकर्ता कार्रवाई कर सकें: "Missing required field (63)" और "Invalid date format (41)"। अंतिम स्टेट में "Completed with issues" अक्सर "Failed" से स्पष्ट रहता है क्योंकि यह यह नहीं बताता कि कुछ भी काम नहीं हुआ।
एक एक्सपोर्टेबल एरर रिपोर्ट भ्रम को एक To‑Do सूची में बदल देती है। सरल रखें: रो या आइटम आईडेंटिफ़ायर, एरर कैटेगरी, एक मानव-समझने योग्य संदेश, और फ़ील्ड नाम जब प्रासंगिक हो।
अगला कदम स्पष्ट और समरी के पास रखें: डेटा ठीक करें और failed आइटम रीट्राई करें, एरर रिपोर्ट डाउनलोड करें, या अगर सिस्टम इशू लगता है तो सपोर्ट से संपर्क करें।
उपयोगकर्ता भरोसा बनाए रखने वाले Cancel और Retry एक्शन
Cancel और Retry सरल दिखते हैं, पर जब UI कुछ कहे और सिस्टम कुछ और करे तो भरोसा जल्दी टूट जाता है। हर जॉब प्रकार के लिए Cancel का मतलब परिभाषित करें और फिर इंटरफ़ेस में उसे ईमानदारी से दर्शाएँ।
आमतौर पर दो मान्य cancel मोड होते हैं:
- "Stop now": वर्कर अक्सर एक cancel फ्लैग चेक करे और जल्दी बाहर निकले।
- "Stop after this step": करंट स्टेप खत्म हो, फिर अगला स्टेप शुरू होने से पहले जॉब रुक जाए।
UI में एक मध्यवर्ती स्टेट दिखाएँ जैसे "Cancel requested" ताकि उपयोगकर्ता बार-बार क्लिक न करें।
कैंसल को सुरक्षित बनाएं—वर्क को दोहराने योग्य बनाकर। अगर जॉब डेटा लिखता है तो आइडेम्पोटेंट ऑपरेशन्स पसंद करें (दुबारा चलाने पर सुरक्षित) और जहाँ ज़रूरी क्लीनअप करें। उदाहरण: CSV इम्पोर्ट रिकॉर्ड बनाता है तो एक job‑run ID स्टोर करें ताकि आप देख सकें कि run #123 में क्या बदला।
रीट्राई में भी वही स्पष्टता चाहिए। जब जॉब resume कर सके तो उसी जॉब इंस्टेंस को रीट्राई करना समझ में आता है। एक नया जॉब इंस्टेंस बनाना तब सुरक्षित होता है जब आप एक साफ रन चाहते हों नया टाइमस्टैम्प और ऑडिट ट्रेल के साथ। किसी भी तरह, बताएं कि क्या होगा और क्या नहीं होगा।
कुछ गार्ड्रेल्स जो कैंसल और रीट्राई को प्रेडिक्टेबल रखते हैं:
- retries को लिमिट करें और काउंट दिखाएँ।
- जॉब रन होते समय Retry डिसेबल करें ताकि डबल रन न हों।
- जब रीट्राई से साइड-इफेक्ट डुप्लिकेट हो सकते हैं (ईमेल, पेमेंट, एक्सपोर्ट), तो कन्फर्मेशन माँगें।
- डिटेल्स पैनल में आखिरी एरर और आखिरी सफल स्टेप दिखाएँ।
कदम-दर-कदम: क्लिक से लेकर पूर्णता तक एंड-टू-एंड फ्लो
एक अच्छा end-to-end फ्लो एक नियम से शुरू होता है: UI काम के लिए कभी नहीं इंतजार करे। इसे केवल जॉब ID का इंतजार करना चाहिए।
फ्लो (यूजर क्लिक से फाइनल स्टेट तक)
-
उपयोगकर्ता टास्क शुरू करता है, API तेज़ी से प्रतिक्रिया देता है। जब उपयोगकर्ता Import या Generate report पर क्लिक करे, सर्वर तुरंत एक जॉब रिकॉर्ड बनाता है और यूनिक जॉब ID लौटाता है।
-
वर्क क्व में डालें और पहला स्टेट सेट करें। जॉब ID को क्यू में डालें और स्टेट को queued व प्रोग्रेस 0% सेट करें। इससे UI के पास कुछ असली दिखाने के लिए हो even before worker picks it up।
-
वर्कर चलाता है और प्रोग्रेस रिपोर्ट करता है। जब वर्कर शुरू करे तो स्टेट को running करें, स्टार्ट टाइम स्टोर करें, और प्रोग्रेस छोटे ईमानदार jumps में अपडेट करें। अगर आप प्रतिशत नहीं माप सकते तो Parsing, Validating, Saving जैसे स्टेप दिखाएँ।
-
UI उपयोगकर्ता को ऑरिएंटेड रखता है। UI polling या subscription से अपडेट लेता है और स्पष्ट स्टेट्स रेंडर करता है। एक छोटा संदेश दिखाएँ (अब क्या हो रहा है) और केवल वही एक्शन दिखाएँ जो अभी प्रासंगिक हों।
-
ड्यूरेबल रिज़ल्ट के साथ फाइनलाइज़ करें। पूरा होने पर finish time, आउटपुट (डाउनलोड रेफरेंस, बने IDs, समरी काउंट), और एरर डिटेल्स स्टोर करें। finished-with-errors को एक अलग परिणाम के रूप में सपोर्ट करें, सिर्फ़ vague success न दिखाएँ।
कैंसल और रीट्राई नियम
Cancel स्पष्ट होना चाहिए: Cancel जॉब रिक्वेस्ट भेजता है, फिर वर्कर acknowledge करता है और canceled मार्क करता है। Retry नया जॉब ID बनाए तो बेहतर होता है—मूल को हिस्ट्री रखकर—और समझाएँ कि क्या री-रन होगा।
उदाहरण परिदृश्य: CSV इम्पोर्ट जिसमें प्रोग्रेस और आंशिक फेल्यर हों
CSV इम्पोर्ट वह जगह है जहाँ प्रगति अपडेट बहुत मायने रखते हैं। कल्पना करें कि एक CRM में sales ops व्यक्ति customers.csv अपलोड करता है जिसमें 8,420 पंक्तियाँ हैं।
अपलोड के तुरंत बाद UI को "मैंने बटन क्लिक किया" से बदलकर "एक जॉब है, और आप जा सकते हैं" पर आ जाना चाहिए। Imports पेज में एक साधारण जॉब कार्ड अच्छा काम करेगा:
- Upload received: "File uploaded. Validating columns..."
- Queued: "Waiting for an available worker (2 jobs ahead)."
- Running: "Importing customers: 3,180 of 8,420 processed (38%)."
- Wrapping up: "Saving results and building a report..."
रन के दौरान एक भरोसेमंद प्रोग्रेस नंबर दिखाएँ (rows processed) और एक छोटी स्टेट लाइन (अभी क्या कर रहा है)। अगर उपयोगकर्ता ने नेविगेट कर लिया है, तो जॉब को Recent jobs क्षेत्र में दिखाएँ।
अब आंशिक फेल्यर जोड़ें। जब जॉब पूरा हो, तो अगर अधिकांश पंक्तियाँ ठीक हैं तो डरावना Failed बैनर दिखाने से बचें। Finished with issues और स्पष्ट विभाजन इस्तेमाल करें:
Imported 8,102 customers. Skipped 318 rows.
शीर्ष कारणों को सरल शब्दों में समझाएँ: invalid email format, missing required fields जैसे company, या duplicate external IDs। उपयोगकर्ता को एक error table डाउनलोड या देखें देने का विकल्प दें जिसमें रो नंबर, ग्राहक नाम और वह फ़ील्ड जो ठीक करनी है दिखाई दे।
Retry सुरक्षित और विशिष्ट लगना चाहिए। प्राथमिक क्रिया हो सकती है Retry failed rows, जो एक नया जॉब बनाएगा जो केवल 318 skipped rows को री‑प्रोसेस करे जब उपयोगकर्ता CSV ठीक कर ले। मूल जॉब को read-only रखें ताकि हिस्ट्री सत्य बनी रहे।
अंत में, परिणाम बाद में आसानी से मिलने चाहिए। हर इम्पोर्ट में एक स्थिर समरी होनी चाहिए: किसने चलाया, कब, फ़ाइल नाम, काउंट (imported, skipped), और एरर रिपोर्ट खोलने का तरीका।
भ्रमित करने वाली प्रगति और रीट्राई के कारण बनने वाली सामान्य गलतियाँ
भरोसा खोने का सबसे तेज़ तरीका है ऐसे नंबर दिखाना जो असल नहीं हैं। एक प्रोग्रेस बार जो दो मिनट तक 0% पर रुका रहे और अचानक 90% तक कूद जाए, वह जुएसन जैसा लगता है। अगर आप सच्चा प्रतिशत नहीं जानते तो स्टेप दिखाएँ (Queued, Processing, Finalizing) या "X of Y items processed" दिखाएँ।
एक और आम समस्या है प्रोग्रेस केवल मेमोरी में स्टोर होना। अगर वर्कर रिस्टार्ट हो जाए, तो UI जॉब भूल सकता है या प्रोग्रेस रीसेट हो सकता है। जॉब स्टेट को ड्यूरेबल स्टोरेज में सेव करें और UI को उसी सिंगल सोर्स ऑफ़ ट्रुथ से पढ़ने दें।
Retry UX तब भी टूटता है जब उपयोगकर्ता एक ही जॉब कई बार शुरू कर सकें। अगर Import CSV बटन अभी भी एक्टिव दिखता है, तो कोई दो बार क्लिक कर देता है और डुप्लिकेट बन जाते हैं। अब retries क्लियर नहीं रहते कि किस रन को फिक्स करना है।
बार-बार होने वाली गलतियाँ:
- नकली प्रतिशत जो असल काम से मेल नहीं खाता
- तकनीकी एरर डंप जो एंड‑यूज़र को दिखाए जाते हैं (स्टैक ट्रेस, कोड)
- टाइमआउट, डुप्लिकेट्स, या आइडेम्पोटेंसी का कोई हैंडलिंग न होना
- रीट्राई जो नया जॉब बनाता है बिना यह समझाए कि क्या होगा
- कैंसल जो सिर्फ़ UI बदलता है, वर्कर बिहेवियर नहीं
एक छोटी पर महत्वपूर्ण बात: यूज़र मैसेज को डेवलपर डिटेल से अलग रखें। उपयोगकर्ता को दिखाएँ "12 rows failed validation" और तकनीकी ट्रेस लॉग में रखें।
रिलीज़ से पहले एक त्वरित चेकलिस्ट
शिप करने से पहले उपयोगकर्ता जो नोटिस करते हैं उन हिस्सों पर एक तेज़ पास करें: स्पष्टता, भरोसा और रिकवरी।
हर जॉब को एक स्नैपशॉट एक्सपोज़ करना चाहिए जिसे आप कहीं भी दिखा सकें: state (queued, running, succeeded, failed, canceled), progress (0-100 या steps), एक छोटा संदेश, timestamps (created, started, finished), और एक result pointer (जहाँ आउटपुट या रिपोर्ट है)।
UI स्टेट्स को स्पष्ट और सुसंगत रखें। उपयोगकर्ताओं को वर्तमान और पिछले जॉब्स खोजने के लिए एक विश्वसनीय जगह चाहिए, और स्पष्ट लेबल जब वे बाद में लौटें ("Completed yesterday", "Still running")। एक Recent jobs पैनल अक्सर बार-बार क्लिक और डुप्लिकेट वर्क रोकता है।
कैंसल और रीट्राई नियम सादे शब्दों में तय करें। तय करें कि हर जॉब प्रकार के लिए Cancel का क्या मतलब है, रीट्राई की अनुमति है या नहीं, और क्या फिर से उपयोग होगा (same inputs, new job ID)। फिर एज केस टेस्ट करें जैसे completion से ठीक पहले कैंसल करना।
आंशिक विफलताओं को एक वास्तविक परिणाम मानें। एक छोटा समरी दिखाएँ ("Imported 97, skipped 3") और एक actionable रिपोर्ट दें जिसे उपयोगकर्ता तुरंत उपयोग कर सके।
रिकवरी की योजना बनाएं। जॉब्स रिस्टार्ट्स से बचकर चलनी चाहिए, और अटकी जॉब्स को टाइमआउट में एक स्पष्ट स्टेट में डालें और मार्गदर्शन दिखाएँ ("Try again" या "Contact support with job ID").
अगले कदम: एक वर्कफ़्लो लागू करें और वहीं से विस्तार करें
उस एक वर्कफ़्लो को चुनें जिसके बारे में उपयोगकर्ता पहले से शिकायत करते हैं: CSV इम्पोर्ट, रिपोर्ट एक्सपोर्ट, बल्क ईमेल भेजना, या इमेज प्रोसेसिंग। छोटे से शुरू करें और बेसिक्स सिद्ध करें: एक जॉब बनता है, यह चलता है, स्टेट रिपोर्ट करता है, और उपयोगकर्ता बाद में उसे पा सकता है।
एक साधारण जॉब हिस्ट्री स्क्रीन अक्सर सबसे बड़ा क्वालिटी सुधार देती है। यह लोगों को लौटने की जगह देती है बजाय इसके कि वे सिर्फ़ एक स्पिनर घूरते रहें।
पहले एक प्रोग्रेस डिलीवरी मेथड चुनें। v1 के लिए polling ठीक है। रिफ्रेश अंतराल इतना धीमा रखें कि बैकएंड पर दया हो, पर इतना तेज़ हो कि जिंदा महसूस हो।
एक व्यावहारिक बिल्ड ऑर्डर जो री-राइट्स से बचाता है:
- पहले जॉब स्टेट्स और ट्रांज़िशन लागू करें (queued, running, succeeded, failed, finished-with-errors)
- एक जॉब हिस्ट्री स्क्रीन basic फिल्टर्स के साथ जोड़ें (last 24 hours, only my jobs)
- केवल तब प्रोग्रेस नंबर जोड़ें जब आप उन्हें ईमानदारी से बनाए रख सकें
- केवल तब कैंसल जोड़ें जब आप consistent cleanup गारंटी कर सकें
- केवल तब रीट्राई जोड़ें जब आप सुनिश्चित हों कि जॉब आइडेम्पोटेंट है
अगर आप बिना कोड लिखे यह बना रहे हैं, तो AppMaster जैसा नो‑कोड प्लेटफ़ॉर्म मदद कर सकता है जिससे आप जॉब स्टेटस टेबल (PostgreSQL) मॉडल कर सकें और वर्कफ़्लोज़ से अपडेट कर सकें, फिर उस स्टेटस को वेब और मोबाइल UI में रेंडर कर सकें। उन टीमों के लिए जो बैकएंड, UI और बैकग्राउंड लॉजिक सभी एक जगह बनाना चाहती हैं, AppMaster (appmaster.io) पूरे ऐप्लिकेशन के लिए डिज़ाइन किया गया है, सिर्फ़ फॉर्म या पेज के लिए नहीं।
सामान्य प्रश्न
एक बैकग्राउंड जॉब तुरंत शुरू होता है और तुरन्त एक जॉब ID लौटाता है, ताकि UI उपयोगी रहे। एक स्लो रिक्वेस्ट वही वेब कॉल खत्म होने तक उपयोगकर्ता को प्रतीक्षा कराती है — इससे रिफ्रेश, डबल-क्लिक्स और डुप्लिकेट सबमिशन होते हैं।
सादगी रखें: queued, running, done और failed, और अगर आप कैंसल सपोर्ट करते हैं तो canceled भी जोड़ें। जब अधिकांश काम सफल हुआ पर कुछ आइटम फेल हुए हों तो “done with issues” जैसा अलग परिणाम दिखाएँ ताकि उपयोगकर्ता यह न समझे कि सब खो गया।
जब उपयोगकर्ता एक्शन शुरू करता है तो तुरंत एक यूनिक जॉब ID लौटाएँ, और उसी ID से एक टास्क रो या कार्ड रेंडर करें। UI को जॉब ID के द्वारा स्टेट पढ़नी चाहिए ताकि उपयोगकर्ता पेज रिफ्रेश करने, टैब बदलने या बाद में वापिस आने पर भी ट्रैक न खोएं।
जॉब स्टेटस को केवल मेमोरी में नहीं, बल्कि एक durable डेटाबेस टेबल में स्टोर करें। सेव करें: करंट स्टेट, टाइमस्टैम्प, प्रोग्रेस वैल्यू, छोटा यूजर-फ्रेंडली मैसेज, और रिज़ल्ट या एरर समरी—ताकि UI हमेशा वही व्यू फिर से बना सके।
केवल तब प्रतिशत (percent) इस्तेमाल करें जब आप ईमानदारी से “X of Y” रिपोर्ट कर सकें। अगर आप वास्तविक डिनॉमिनेटर नहीं बता सकते, तो स्टेप-आधारित प्रोग्रेस दिखाएँ जैसे “Validating”, “Importing”, “Finalizing” और मैसेज अपडेट रखें ताकि यूजर को आगे बढ़ते हुए लगे।
Polling सबसे सरल है; शुरुआत में हर 2–5 सेकंड पर, फिर लंबे जॉब पर धीरे कर दें। Push तुरंत महसूस कराता है, पर कनेक्शन गिरने पर fallback चाहिए। इसलिए शुरुआत में polling रखें और जहाँ ज़रूरत हो वहाँ push जोड़ें।
अपडेट्स जब रुक जाएँ तो इसे एक वास्तविक स्थिति के रूप में दिखाएँ। उदाहरण: “Last updated 2 minutes ago” और मैन्युअल रिफ्रेश का विकल्प दें। बैकएंड पर heartbeat मिस होने पर जॉब को stale मार्क करें और स्पष्ट मार्गदर्शन दिखाएँ—जैसे retry या सपोर्ट से संपर्क करें (जॉब ID दें)।
अगला कदम स्पष्ट रखें: क्या यूजर काम जारी रख सकता है, पेज छोड़ सकता है, या सुरक्षित रूप से कैंसल कर सकता है। एक मिनट से लंबी किसी भी चीज़ के लिए एक समर्पित Jobs/Activity व्यू रखें ताकि लोग बाद में रिज़ल्ट्स पा सकें और सिर्फ़ स्पिनर को न घूरते रहें।
इसे एक मान्य परिणाम मानें और दोनों हिस्से साफ़ दिखाएँ, जैसे: “Imported 9,380 of 9,500. 120 failed.” फिर एक छोटा, actionable एरर समरी दें जिसे उपयोगकर्ता बिना लॉग पढ़े ठीक कर सके; तकनीकी डिटेल्स आंतरिक लॉग में रखें।
हर जॉब के लिए स्पष्ट परिभाषा रखें कि Cancel का क्या मतलब है और UI में इसे ईमानदारी से दिखाएँ—एक intermediate “cancel requested” स्टेट दिखाएँ ताकि लोग बार-बार क्लिक न करें। काम को आइडेम्पोटेंट बनाना बेहतर है; retries को सीमित करें और तय करें कि retry उसी जॉब को resume करेगा या नया जॉब बनाएगा।


