एक्सपोर्ट टाइमआउट रोकें: ऐसिंक जॉब्स, प्रगति, स्ट्रीमिंग
बड़े CSV और PDF रिपोर्ट्स के लिए ऐसिंक जॉब्स, प्रगति संकेतक, पेजिंग और स्ट्रीमिंग डाउनलोड लागू करके एक्सपोर्ट टाइमआउट रोकें।

सरल शब्दों में: एक्सपोर्ट क्यों टाइमआउट होते हैं
एक एक्सपोर्ट तब टाइमआउट होता है जब सर्वर कड़ी होने से पहले काम पूरा नहीं कर पाता। वह सीमा आपके ब्राउज़र, रिवर्स प्रॉक्सी, ऐप सर्वर, या डेटाबेस कनेक्शन में कहीं भी सेट हो सकती है। उपयोगकर्ताओं के लिए यह अक्सर यादृच्छिक लगता है क्योंकि कभी-कभी एक्सपोर्ट सफल होता है और कभी नहीं।
स्क्रीन पर यह आमतौर पर इन में से किसी एक तरह दिखता है:
- एक स्पिनर जो कभी खत्म नहीं होता
- एक डाउनलोड जो शुरू होता है और फिर "network error" के साथ रुक जाता है
- लंबा इंतजार करने के बाद एक एरर पेज
- एक फाइल जो डाउनलोड तो हो जाती है पर खाली या करप्ट होती है
बड़े एक्सपोर्ट परेशान करते हैं क्योंकि ये सिस्टम के कई हिस्सों पर एक साथ दबाव डालते हैं। डेटाबेस को बहुत सारी पंक्तियाँ ढूँढनी और जोड़नी होती हैं। ऐप सर्वर को उन्हें CSV में फॉर्मेट करना या PDF में रेंडर करना होता है। फिर ब्राउज़र को एक बड़ी रिस्पॉन्स प्राप्त करनी होती है बिना कनेक्शन टूटे।
विशाल datasets स्पष्ट ट्रिगर हैं, पर "छोटे" एक्सपोर्ट भी भारी हो सकते हैं: महंगे joins, कई कैलकुलेटेड फील्ड, प्रति-पंक्ति लुकअप्स, और खराब इंडेक्स वाले फिल्टर्स एक सामान्य रिपोर्ट को टाइमआउट बना सकते हैं। PDF विशेष रूप से जोखिम भरे होते हैं क्योंकि उनमें लेआउट, फॉन्ट, इमेज, पेज ब्रेक और अक्सर संबंधित डेटा के अतिरिक्त क्वेरीज शामिल होते हैं।
रीट्राइ अक्सर चीज़ों को और खराब करते हैं। जब उपयोगकर्ता रिफ्रेश करता है या फिर से Export दबाता है, तो आपका सिस्टम वही काम दो बार शुरू कर सकता है—अब डेटाबेस डुप्लिकेट क्वेरीज चलाता है, ऐप सर्वर डुप्लिकेट फाइल बनाता है, और लोड उसी समय बढ़ जाता है जब सिस्टम पहले से ही संघर्ष कर रहा होता है।
यदि आप एक्सपोर्ट टाइमआउट रोकना चाहते हैं, तो एक्सपोर्ट को सामान्य पेज लोड की तरह न देखें—इसे बैकग्राउंड टास्क मानें। यहाँ तक कि कोई-कोड बिल्डर में भी जैसे AppMaster, पैटर्न टूल से ज्यादा मायने रखता है: लंबा काम अलग फ्लो मांगता है, न कि "बटन दबाओ, इंतजार करो"।
अपनी ऐप के लिए सही एक्सपोर्ट पैटर्न चुनें
ज़्यादातर एक्सपोर्ट फेल्यर इसलिए होते हैं क्योंकि ऐप हर स्थिति के लिए एक ही पैटर्न इस्तेमाल करता है, जबकि डेटा साइज और प्रोसेसिंग समय काफी बदल सकते हैं।
एक सिंपल सिंक्रोनस एक्सपोर्ट (यूज़र क्लिक करता है, सर्वर जेनरेट करता है, डाउनलोड शुरू होता है) तब ठीक है जब एक्सपोर्ट छोटा और अनुमानित हो—कुछ सौ पंक्तियाँ, बेसिक कॉलम, भारी फ़ॉर्मैटिंग न हो, और ज़्यादा उपयोगकर्ता एक साथ न हों। अगर यह लगातार कुछ ही सेकंड में खत्म हो जाता है तो सादगी बेहतर है।
किसी भी लंबे या अनिश्चित काम के लिए, ऐसिंक एक्सपोर्ट जॉब्स का उपयोग करें। यह बड़े datasets, जटिल कैलकुलेशन, PDF लेआउट वर्क और शेयर किए गए सर्वरों के लिए बेहतर है जहाँ एक धीमा एक्सपोर्ट बाकी अनुरोधों को ब्लॉक कर सकता है।
ऐसिंक जॉब तब बेहतर हैं जब:
- एक्सपोर्ट नियमित रूप से 10–15 सेकंड से अधिक लेते हैं
- उपयोगकर्ता चौड़े डेट रेंज या "all time" मांगते हैं
- आप चार्ट, इमेज, या कई पेज वाले PDFs जेनरेट करते हैं
- कई टीमें पीक घंटों में एक्सपोर्ट करती हैं
- आपको फेल होने पर सुरक्षित रीट्राइ चाहिए
स्ट्रीमिंग डाउनलोड भी मदद कर सकता है जब एक्सपोर्ट बड़ा हो पर उसे क्रमवार बनाया जा सके। सर्वर तुरंत बाइट्स भेजना शुरू करता है, जिससे यह तेज़ महसूस होता है और सारी फाइल मेमोरी में बिल्ड करने से बचते हैं। यह लंबे CSV डाउनलोड के लिए शानदार है, पर कम उपयोगी है अगर आपको पहली लाइन लिखने से पहले सब कुछ कम्प्यूट करना जरूरी हो।
आप तरीकों को मिला भी सकते हैं: ऐसिंक जॉब में एक्सपोर्ट जेनरेट कराएँ (या स्नैपशॉट तैयार करें), फिर तैयार होने पर स्ट्रीम करें। AppMaster में एक व्यावहारिक तरीका है: एक "Export Requested" रिकॉर्ड बनाएं, बैकएंड बिज़नेस प्रोसेस में फाइल जेनरेट करें, और उपयोगकर्ता को बिना ब्राउज़र रिक्वेस्ट खोले ही तैयार परिणाम डाउनलोड करने दें।
चरण-दर-चरण: एक ऐसिंक एक्सपोर्ट जॉब बनाना
सबसे बड़ा बदलाव सरल है: उपयोगकर्ता क्लिक करते ही उसी रिक्वेस्ट के अंदर फाइल जनरेट करना बंद कर दें।
एक ऐसिंक एक्सपोर्ट जॉब काम को दो हिस्सों में बाँटता है: एक तेज़ रिक्वेस्ट जो जॉब बनाता है, और बैकग्राउंड वर्क जो फाइल बनाता है जबकि ऐप रिस्पॉन्सिव रहता है।
एक व्यावहारिक 5-स्टेप फ्लो
- एक्सपोर्ट रिक्वेस्ट कैप्चर करें (किसने माँगा, फ़िल्टर, चुने गए कॉलम, आउटपुट फॉर्मेट)।
- एक जॉब रिकॉर्ड बनाएं जिसमें स्टेटस (queued, running, done, failed), टाइमस्टैम्प और एरर फ़ील्ड हो।
- भारी काम बैकग्राउंड में चलाएँ—क्यू, शेड्यूल्ड वर्कर, या डेडिकेटेड वर्कर प्रोसेस का उपयोग करें।
- परिणाम स्टोरेज में लिखें (object storage या file store), फिर जॉब रिकॉर्ड पर डाउनलोड रेफरेंस सेव करें।
- उपयोगकर्ता को तैयार होने पर इन-ऐप नोटिफिकेशन, ईमेल, या आपकी टीम के किसी मैसेज चैनल से बताएं।
जॉब रिकॉर्ड को सत्य का स्रोत रखें। यदि उपयोगकर्ता रिफ्रेश करे, डिवाइस बदलें, या टैब बंद कर दे, तो आप वही जॉब स्टेटस और वही डाउनलोड बटन दिखा सकते हैं।
उदाहरण: एक सपोर्ट मैनेजर पिछली तिमाही के सभी टिकट एक्सपोर्ट करता है। स्पिनिंग टैब के बजाय वे देखते हैं कि एक जॉब queued से done में जाता है, और फिर डाउनलोड दिखाई देता है। AppMaster में आप Data Designer में जॉब टेबल मॉडल कर सकते हैं, Business Process Editor में बैकग्राउंड लॉजिक बना सकते हैं, और UI स्टेट को एक स्टेट्स फ़ील्ड से चलवा सकते हैं।
उपयोगकर्ता वास्तव में भरोसा करने वाले प्रगति संकेतक
एक अच्छा प्रगति संकेतक चिंता कम करता है और लोगों को Export पांच बार दबाने से रोकता है। यह अप्रत्यक्ष रूप से एक्सपोर्ट टाइमआउट भी रोकता है क्योंकि उपयोगकर्ता असली प्रगति देखकर इंतजार करने को तैयार रहते हैं।
लोगों के समझने वाले रूप में प्रगति दिखाइए। सिर्फ प्रतिशत अक्सर भ्रामक होता है, इसलिए इसे कुछ ठोस के साथ जोड़े:
- वर्तमान कदम (Preparing data, Fetching rows, Building file, Uploading, Ready)
- प्रोसेस हुए rows में से कुल (या प्रोसेस किए गए पेज)
- कब शुरू हुआ और आख़िरी अपडेट कब हुआ
- अनुमानित शेष समय (सिर्फ तभी जब यह काफी स्थिर रहे)
नकली सटीकता से बचें। अगर आपको कुल काम नहीं पता तो 73% मत दिखाइए। पहले माइलस्टोन दिखाएँ, फिर जैसे ही डिनॉमिनेटर पता चले प्रतिशत दिखाएँ। एक सरल पैटर्न है: सेटअप के लिए 0%–10%, पंक्तियों के आधार पर 10%–90%, और फाइल फाइनलाइज़ेशन के लिए 90%–100%। PDF के लिए, छोटे सत्य जैसे "records rendered" या "sections completed" ट्रैक करें।
काफ़ी बार अपडेट करें ताकि यह जीवित लगे, पर इतना अक्सर नहीं कि आप डेटाबेस या क्यू पर भारी पड़ें। आम तौर पर हर 1–3 सेकंड या हर N रिकॉर्ड (जैसे हर 500 या 1,000 पंक्तियाँ) पर प्रगति लिखें—जो भी कम बार हो। एक हल्का हार्टबीट टाइमस्टैम्प भी रिकॉर्ड करें ताकि UI तब भी कह सके "Still working" जब प्रतिशत नहीं बढ़ रहा हो।
लोगों को नियंत्रण दें जब चीज़ें अपेक्षा से अधिक समय लें। उन्हें चल रहे एक्सपोर्ट को रद्द करने दें, नया शुरू करने दें बिना पहले वाला खोए, और एक्सपोर्ट हिस्ट्री दिखाएँ जिसमें स्टेटस (Queued, Running, Failed, Ready) और छोटा एरर मैसेज हो।
AppMaster में एक सामान्य रिकॉर्ड दिखता है: ExportJob (status, processed_count, total_count, step, updated_at)। UI उस रिकॉर्ड को पोल करता है और ऐसिंक जॉब बैकग्राउंड में फ़ाइल जेनरेट करते हुए ईमानदार प्रगति दिखाता है।
पेजिंग और फ़िल्टरिंग: काम को सीमित रखें
ज़्यादातर टाइमआउट इसलिए होते हैं क्योंकि एक्सपोर्ट एक ही बार में सब कुछ करने की कोशिश करता है: बहुत सारी पंक्तियाँ, बहुत सारे कॉलम, बहुत सारे joins। सबसे तेज़ फिक्स यह है कि काम को सीमित रखें ताकि उपयोगकर्ता डेटा का छोटा, साफ़ हिस्सा एक्सपोर्ट करें।
उपयोगकर्ता के लक्ष्य से शुरू करें। अगर किसी को "पिछले महीने के फेल हुए इनवॉइस" चाहिए, तो डिफ़ॉल्ट "सभी इनवॉइस" न रखें। फ़िल्टर को सामान्य लगने दें, न कि बोझिल। एक साधारण डेट रेंज और एक-दो कीस्टेटस अक्सर डेटासेट को 90% तक घटा देता है।
अच्छे एक्सपोर्ट फॉर्म में आम तौर पर डेट रेंज (सेंसिबल डिफ़ॉल्ट जैसे पिछले 7 या 30 दिन), एक-दो की स्टेटस, वैकल्पिक सर्च या ग्राहक/टीम चयन, और संभव हो तो काउंट प्रीव्यू (यहाँ तक कि अनुमान) शामिल होते हैं।
सर्वर साइड पर, पेजिंग का उपयोग करके डेटा चंक में पढ़ें। इससे मेमोरी स्थिर रहती है और प्रगति के लिए नेचुरल चेकपॉइंट मिलते हैं। पेजिंग करते समय हमेशा एक स्थिर ऑर्डर का उपयोग करें (उदाहरण के लिए order by created_at, id)—बिना इसके नए रिकॉर्ड्स पहले के पेजों में घुस सकते हैं और आप रिकॉर्ड्स मिस या डुप्लीकेट कर देंगे।
लंबे एक्सपोर्ट के दौरान डेटा बदलता है—तो तय करें कि "कंसिस्टेंट" का क्या मतलब है। एक सरल तरीका है कि जॉब शुरू होने पर एक स्नैपशॉट टाइम रिकॉर्ड करें और सिर्फ उसी टाइमस्टैम्प तक की पंक्तियाँ एक्सपोर्ट करें। अगर आपको सख्त कंसिस्टेंसी चाहिए तो डेटाबेस के जो विकल्प हैं जैसे कंसिस्टेंट रीड या ट्रांज़ैक्शन उपयोग करें।
कोई-कोड टूल जैसे AppMaster में यह साफ़ तौर पर बिज़नेस प्रोसेस से मैप हो जाता है: फ़िल्टर वैलिडेट करें, स्नैपशॉट टाइम सेट करें, फिर पेजेज के माध्यम से तब तक लूप करें जब तक कुछ बचा हो।
सर्वर न तोड़ते हुए स्ट्रीमिंग डाउनलोड
स्ट्रीमिंग का मतलब है कि आप उपयोगकर्ता को फाइल भेजना तब शुरू करते हैं जब आप अभी भी उसे बना रहे होते हैं। सर्वर को पूरी CSV या PDF मेमोरी में पहले बनाकर रखने की ज़रूरत नहीं रहती। यह बड़े फाइल्स के समयआउट रोकने के सबसे भरोसेमंद तरीकों में से एक है।
स्ट्रीमिंग धीमी क्वेरीज को अचानक तेज नहीं बनाती। अगर डेटाबेस वर्क पहले बाइट से पहले पाँच मिनट लेता है, तो रिक्वेस्ट फिर भी टाइमआउट कर सकता है। सामान्य समाधान स्ट्रीमिंग को पेजिंग के साथ मिलाना है: एक चंक लीजिए, लिखिए, और आगे बढ़िए।
मेमोरी कम रखने के लिए जैसे-तैसे लिखें। एक चंक जेनरेट करें (उदाहरण: 1,000 CSV पंक्तियाँ या एक PDF पेज), उसे रिस्पॉन्स में लिखें, फिर फ्लश करें ताकि क्लाइंट डेटा लगातार प्राप्त करता रहे। "बाद में सॉर्ट करने के लिए सभी पंक्तियाँ एक बड़े एरे में इकट्ठा करना" से बचें। अगर आपको स्थिर ऑर्डर चाहिए तो डेटाबेस में ही सॉर्ट करें।
हेडर, नाम और कंटेंट टाइप
साफ़ हेडर भेजें ताकि ब्राउज़र और मोबाइल ऐप्स डाउनलोड को सही तरीके से ट्रीट करें। सही content type सेट करें (जैसे text/csv या application/pdf) और एक सुरक्षित फ़ाइलनाम रखें। फ़ाइलनाम स्पेशल कैरेक्टर से बचें, छोटा रखें, और अगर उपयोगकर्ता बार-बार वही रिपोर्ट एक्सपोर्ट करते हैं तो टाइमस्टैम्प जोड़ें।
रिस्यूम और आंशिक डाउनलोड
पहले तय कर लें कि आप resume सपोर्ट करते हैं या नहीं। बेसिक स्ट्रीमिंग अक्सर byte-range resume सपोर्ट नहीं करती, खासकर जनरेट की जाने वाली PDFs के लिए। अगर आप इसे सपोर्ट करते हैं, तो आपको Range रिक्वेस्ट्स हैंडल करनी होंगी और उसी जॉब के लिए कनसिस्टेंट आउटपुट जेनरेट करना होगा।
शिप करने से पहले सुनिश्चित करें:
- हेडर बॉडी लिखने से पहले भेजें, फिर चंक्स में लिखें और फ्लश करें
- चंक साइज स्थिर रखें ताकि लोड के तहत मेमोरी फ्लैट रहे
- डिटर्मिनिस्टिक ऑर्डर का उपयोग करें ताकि उपयोगकर्ता आउटपुट पर भरोसा कर सकें
- डॉक्युमेंट करें कि resume सपोर्ट है या नहीं और कनेक्शन ड्रॉप होने पर क्या होगा
- सर्वर-साइड लिमिट्स लगाएँ (max rows, max time) और हर लिमिट पहुँचने पर दोस्ताना एरर लौटाएँ
यदि आप AppMaster में एक्सपोर्ट बनाते हैं, तो जनरेशन लॉजिक बैकएंड फ्लो में रखें और ब्राउज़र से नहीं—सर्वर साइड से स्ट्रीम करें।
बड़े CSV एक्सपोर्ट: व्यावहारिक तरकीबें
बड़े CSV के लिए, फाइल को एक सिंगल ब्लॉब की तरह संभालना बंद कर दें। इसे लूप की तरह बनाएं: डेटा का एक स्लाइस पढ़ें, पंक्तियाँ लिखें, दोहराएँ। इससे मेमोरी स्थिर रहती है और रीट्राइ सुरक्षित होते हैं।
CSV पंक्ति-दर-पंक्ति लिखें। भले ही आप ऐसिंक जॉब में जेनरेट कर रहे हों, "सभी पंक्तियाँ इकट्ठा करें और फिर stringify करें" से बचें। एक राइटर खोला रखें और जैसे ही पंक्ति तैयार हो, जोड़ते जाएँ। अगर आपकी स्टैक सपोर्ट करती है, तो डेटाबेस करसर या पेजिंग का उपयोग करें ताकि आप कभी भी लाखों रिकॉर्ड एक साथ लोड न करें।
CSV की सहीता उतनी ही महत्वपूर्ण है जितनी स्पीड। फाइल ठीक दिख सकती है जब तक कोई Excel में खोलता है और कॉलम शिफ्ट हो जाते हैं।
CSV नियम जो फाइल को टूटने से बचाते हैं
- हमेशा कॉमा, कोट्स और न्यूलाइन को एस्केप करें (पूरा फ़ील्ड को कोट्स में रखें और भीतरी कोट्स को डबल करें)
- UTF-8 आउटपुट करें और गैर-अंग्रेज़ी नामों का एंड-टू-एंड परीक्षण करें
- एक स्थिर हेडर रो उपयोग करें और रन दर रन कॉलम ऑर्डर फिक्स रखें
- तारीखें और दशमलव सामान्य करें (एक फॉर्मेट चुनें और उसी पर स्थिर रहें)
- अगर डेटा =, +, -, या @ से शुरू हो सकता है तो सूत्रों से बचें
परफॉर्मेंस अक्सर लिखने की बजाय डेटा एक्सेस पर मरती है। N+1 लुकअप पर ध्यान रखें (जैसे लूप के अंदर हर ग्राहक लोड करना)। रिलेटेड डेटा एक ही क्वेरी में लाएँ या जो चाहिए उसे पहले प्रीलोड करें, फिर पंक्तियाँ लिखें।
जब एक्सपोर्ट वास्तव में बहुत बड़े हों, उन्हें जानबूझकर विभाजित करें। एक व्यवहारिक तरीका है महीनेवार फाइलें—उदाहरण के लिए 5 साल के ऑर्डर को 60 मासिक फाइलों में बाँटना ताकि एक धीमा महीना सब कुछ ब्लॉक न करे।
AppMaster का उपयोग करते समय, Data Designer में dataset मॉडल करें और बिज़नेस प्रोसेस में बैकग्राउंड में export चलाएं, पेजिंग करते हुए पंक्तियाँ लिखें।
बड़े PDF एक्सपोर्ट: उन्हें अनुमान योग्य रखें
PDF जेनरेशन आमतौर पर CSV से धीमा होता है क्योंकि यह CPU-भारी होता है। आप सिर्फ डेटा मूव नहीं कर रहे—आप पेज लेआउट कर रहे हैं, फॉन्ट प्लेस कर रहे हैं, टेबल ड्रॉ कर रहे हैं, और अक्सर इमेजेस का साइज बदल रहे हैं। PDF को बैकग्राउंड टास्क और स्पष्ट सीमाओं के साथ संभालें—यह तेज़ प्रतिक्रिया नहीं है।
टेम्पलेट चुनाव यह तय करते हैं कि क्या 2 मिनट वाला एक्सपोर्ट 20 मिनट बन जाएगा। सरल लेआउट जीतते हैं: कम कॉलम, कम नेस्टेड टेबल, और अनुमानित पेज ब्रेक्स। इमेजेस सबसे तेज़ तरीके से सब कुछ धीमा कर देती हैं, खासकर अगर वे बड़ी, उच्च DPI, या रिमोट स्टोरेज से रेंडरिंग के दौरान लोड होती हैं।
स्पीड और भरोसेमंदता बढ़ाने वाले टेम्पलेट निर्णय:
- एक या दो फॉन्ट का उपयोग करें और भारी fallback चेन से बचें
- हेडर और फुटर सरल रखें (हर पेज पर डायनामिक चार्ट न लगाएँ)
- बड़े रास्टर इमेज की जगह वेक्टर आइकन पसंद करें
- "auto fit" लेआउट से बचें जो टेक्स्ट को कई बार री-मेज़र करे
- जटिल ट्रांसपेरेन्सी और शैडो से बचें
बड़े एक्सपोर्ट के लिए, बैच में रेंडर करें। एक बार में एक सेक्शन या छोटा पेज रेंज जेनरेट करें, उसे टेम्पररी फाइल में लिखें, और तब अंतिम PDF असेंबल करें। इससे मेमोरी स्थिर रहती है और अगर वर्कर बीच में क्रैश हो तो रीट्राइ सुरक्षित होते हैं। यह ऐसिंक जॉब्स और अर्थपूर्ण प्रगति स्टेप्स के साथ भी अच्छी तरह जोड़ा जा सकता है (उदाहरण: "Preparing data", "Rendering pages 1-50", "Finalizing file")।
साथ ही यह पूछें कि क्या उपयोगकर्ता को वास्तव में PDF चाहिए। अगर उन्हें ज़्यादातर पंक्तियाँ और कॉलम चाहिए तो CSV दें और PDF को सारांश के लिए सीमित रखें।
AppMaster में यह नेचुरल फिट बैठता है: PDF जेनरेशन को बैकग्राउंड जॉब बनाएं, प्रगति रिपोर्ट करें, और जॉब पूरा होने पर फाइल डाउनलोड के रूप में दें।
सामान्य गलतियाँ जो टाइमआउट पैदा करती हैं
एक्सपोर्ट फेल्यर आमतौर पर रहस्यमय नहीं होते—कुछ विकल्प 200 पंक्तियों पर ठीक रहते हैं और 200,000 पर टूट जाते हैं।
सबसे सामान्य गलतियाँ:
- पूरा एक्सपोर्ट एक वेब रिक्वेस्ट के अंदर चलाना। ब्राउज़र इंतजार करता है, सर्वर वर्कर व्यस्त रहता है, और कोई धीमा क्वेरी या बड़ी फाइल आपको समय सीमाओं से पार ले जा सकती है।
- समय के बजाय काम पर आधारित प्रगति दिखाना। एक टाइमर जो 90% तक दौड़ता है और फिर अटक जाता है, उपयोगकर्ताओं को रिफ्रेश, कैंसिल, या नया एक्सपोर्ट शुरू करने पर मजबूर करता है।
- सभी पंक्तियों को मेमोरी में पढ़ना फिर फ़ाइल लिखना—सरल लेकिन मेमोरी लिमिट पार करने का तेज़ तरीका।
- लंबे डेटाबेस ट्रांज़ैक्शंस पकड़ कर रखना या लॉक्स की अनदेखी करना। एक्सपोर्ट क्वेरीज लिखने को ब्लॉक कर सकती हैं या लेखन से ब्लॉक हो सकती हैं, और धीमन पूरे ऐप में फैल सकता है।
- असीमित एक्सपोर्ट की अनुमति और कोई क्लीनअप न होना। बार-बार क्लिक से जॉब्स भर जाते हैं, स्टोरेज फुल हो जाती है, और पुराने फाइल्स चारों तरफ पड़ जाते हैं।
एक ठोस उदाहरण: एक सपोर्ट लीड पिछले दो वर्षों के सभी टिकट एक्सपोर्ट करता है और दो बार क्लिक कर देता है क्योंकि कुछ नहीं हुआ दिखता। अब दो एक जैसे एक्सपोर्ट एक ही डेटाबेस के लिए प्रतिस्पर्धा करते हैं, दोनों मेमोरी में बड़ी फाइल बनाते हैं, और दोनों टाइमआउट हो जाते हैं।
अगर आप यह AppMaster जैसे नो-कोड टूल में बना रहे हैं, तो यही नियम लागू होते हैं: एक्सपोर्ट को रिक्वेस्ट पाथ से बाहर रखें, प्रगति को पंक्तियों के आधार पर ट्रैक करें, आउटपुट को जैसे-तैसे लिखें, और प्रति-उपयोगकर्ता कितने एक्सपोर्ट एक साथ चल सकते हैं उस पर सरल सीमाएँ लगाएं।
शिप करने से पहले जल्दी से चेक करें
प्रोडक्शन में एक्सपोर्ट फीचर रिलीज़ करने से पहले एक त्वरित पास करें: लंबा काम रिक्वेस्ट के बाहर हो, उपयोगकर्ता ईमानदार प्रगति देखें, और सर्वर सब कुछ एक साथ करने की कोशिश न करे।
एक त्वरित प्री-फ्लाइट चेकलिस्ट:
- बड़े एक्सपोर्ट बैकग्राउंड जॉब के रूप में चलते हैं (छोटे, भरोसेमंद तेज़ वाले सिंक्रोनस हो सकते हैं)
- उपयोगकर्ता queued, running, done, failed जैसी साफ़ स्टेट्स के साथ timestamps देखें
- डेटा चंक्स में पढ़ा जाता है और स्थिर सॉर्ट ऑर्डर है (उदा., created time + ID)
- तैयार फाइल बाद में बिना फिर से चलाए डाउनलोड की जा सकती है, भले ही उपयोगकर्ता टैब बंद कर दे
- पुराने फाइल्स और जॉब हिस्ट्री के लिए सीमा और क्लीनअप योजना हो (उम्र-आधारित डिलीशन, प्रति-यूज़र मैक्स जॉब्स, स्टोरेज कैप)
एक अच्छा सेंटी टेस्ट यह है कि अपनी सबसे खराब स्थिति कोशिश करें: वह सबसे बड़ा डेट रेंज एक्सपोर्ट करें जिसे आप अनुमति देते हैं, जबकि कोई और सक्रिय रूप से रिकॉर्ड जोड़ रहा हो। अगर आप डुप्लिकेट, मिसिंग रो, या अटकी प्रगति देखते हैं तो आपकी ऑर्डरिंग या चंकिंग स्थिर नहीं है।
AppMaster पर बनाते समय, ये चेक्स वास्तविक हिस्सों से साफ़ मैप होते हैं: Business Process Editor में बैकग्राउंड प्रोसेस, डेटाबेस में एक एक्सपोर्ट जॉब रिकॉर्ड, और एक स्टेटस फ़ील्ड जिसे आपकी UI पढ़े और रिफ्रेश करे।
फेल्यर को सुरक्षित बनाइए। एक फेल्ड जॉब अपनी एरर मैसेज रखें, रीट्राइ की अनुमति दें, और अधूरी फाइलें "तैयार" जैसी न दिखें।
उदाहरण: वर्षों के डेटा को एक्सपोर्ट करना बिना ऐप फ्रीज़ हुए
एक ops मैनेजर को हर महीने दो एक्सपोर्ट चाहिए: विश्लेषण के लिए पिछले 2 वर्षों के ऑर्डर्स का CSV, और अकाउंटिंग के लिए मासिक इनवॉयस PDFs का सेट। अगर आपकी ऐप यह सब सामान्य वेब रिक्वेस्ट में बनाने की कोशिश करेगी, तो आप अंततः टाइम लिमिट्स को पार कर लेंगे।
शुरू करें काम को बाँधकर। एक्सपोर्ट स्क्रीन डेट रेंज (डिफ़ॉल्ट: पिछले 30 दिन), वैकल्पिक फिल्टर्स (status, region, sales rep), और स्पष्ट कॉलम चयन माँगती है। यह एक परिवर्तन अक्सर 2 साल के, 2 मिलियन-रो प्रॉब्लम को मैनेज करने योग्य बना देता है।
जब उपयोगकर्ता Export दबाता है, तो ऐप एक Export Job रिकॉर्ड बनाता है (type, filters, requested_by, status, progress, error_text) और उसे क्यू में डालता है। AppMaster में यह Data Designer मॉडल और बैकग्राउंड Business Process के रूप में काम करता है।
जब जॉब चल रहा होता है, UI उपयोगकर्ता को विश्वसनीय स्टेट दिखाता है: queued, processing (उदा., 3 of 20 chunks), generating file, ready (download बटन), या failed (साफ़ एरर और रीट्राइ)।
चंकिंग प्रमुख डिटेल है। CSV जॉब ऑर्डर्स को पेज में पढ़ता है (मान लें 50,000 प्रति पेज), हर पेज को आउटपुट में लिखता है, और हर चंक के बाद प्रगति अपडेट करता है। PDF जॉब भी महीनेवार बैच करता है ताकि एक धीमा महीना सब कुछ ब्लॉक न करे।
अगर कुछ टूटता है (खराब फिल्टर, परमिशन मिसिंग, स्टोरेज एरर), जॉब को Failed मार्क करें और उपयोगकर्ता के लिए एक छोटा actionable संदेश दें: "March invoices generate नहीं हुए। कृपया फिर से प्रयास करें या सहायता से Job ID 8F21 के साथ संपर्क करें." रीट्राइ वही फिल्टर्स री-यूज़ करता है ताकि उपयोगकर्ता फिर से शुरुआत न करे।
अगले कदम: एक्सपोर्ट को फायर-ड्रिल नहीं, इन-बिल्ट फीचर बनाएं
लंबी अवधि में एक्सपोर्ट टाइमआउट रोकने का तेज़ तरीका यही है कि एक्सपोर्ट्स को वन-ऑफ बटन न मानें और उन्हें एक मानकीकृत पैटर्न बनाकर दीजिए।
एक डिफ़ॉल्ट तरीका चुनें और हर जगह लागू करें: ऐसिंक जॉब बैकग्राउंड में फाइल जेनरेट करे, फिर उपयोगकर्ता को तैयार होने पर डाउनलोड मिल जाए। यह एक निर्णय अधिकांश "टेस्ट में काम किया" वाले सरप्राइज़ दूर कर देगा क्योंकि उपयोगकर्ता की रिक्वेस्ट को पूरी फाइल के लिए इंतजार नहीं करना होगा।
लोगों के लिए यह आसान बनाएं कि उन्होंने पहले क्या जनरेट किया है। एक एक्सपोर्ट हिस्ट्री पेज (प्रति-उपयोगकर्ता, प्रति-वर्कस्पेस, या प्रति-एकाउंट) रिपीट एक्सपोर्ट्स घटाता है, सपोर्ट टीम्स को "मुझे मेरी फाइल कहां मिली?" का जवाब देने में मदद करता है, और आपको स्टेटस, एरर्स और एक्सपायरी दिखाने के लिए सही जगह देता है।
अगर आप यह पैटर्न AppMaster में बना रहे हैं, तो प्लेटफ़ॉर्म वास्तविक सोर्स कोड जेनरेट करता है और बैकएंड लॉजिक, DB मॉडलिंग, और वेब/मोबाइल UI एक ही स्थान पर सपोर्ट करता है। तेज़ ऐसिंक एक्सपोर्ट जॉब जल्दी शिप करने वाली टीम्स के लिए appmaster.io अक्सर इस काम के लिए इस्तेमाल किया जाता है—Export Job टेबल, बैकग्राउंड प्रोसेस, और प्रगति UI बिना सब कुछ हाथ से जोड़ने के।
फिर मापें कि वास्तव में क्या दर्द देता है। स्लो डेटाबेस क्वेरीज, CSV जेनरेशन में बिताया समय, और PDF रेंडर का समय ट्रैक करें। आपको परफेक्ट ऑब्ज़रविबिलिटी की ज़रूरत नहीं—एक्सपोर्ट के दौरान लॉग की गई अवधि और रो काउंट्स जल्दी दिखा देंगे कि कौन सा रिपोर्ट या फिल्टर कॉम्बिनेशन असली समस्या है।
एक्सपोर्ट्स को किसी भी अन्य प्रोडक्ट फीचर की तरह ट्रीट करें: यह निरंतर, मापने योग्य और सपोर्ट करने में आसान होना चाहिए।
सामान्य प्रश्न
एक्सपोर्ट तब टाइमआउट होता है जब काम किसी भी कारण से अनुरोध-पाथ पर सेट सीमा से पहले पूरा नहीं होता। यह सीमा ब्राउज़र, रिवर्स प्रॉक्सी, आपका ऐप सर्वर, या डेटाबेस कनेक्शन किसी से भी आ सकती है, इसलिए कभी-कभी यह रैंडम लगता है भले ही मूल कारण धीमे क्वेरीज या हाई लोड से जुड़ा हो।
सिंक्रोनस "क्लिक और डाउनलोड" एक्सपोर्ट सिर्फ तब ठीक है जब वह लगातार कुछ ही सेकंड में और छोटे, अनुमानित डेटा सेट के साथ खत्म हो जाता है। अगर एक्सपोर्ट अक्सर 10–15 सेकंड से ज्यादा लेता है, बड़े डेट रेंज शामिल हैं, भारी कैलकुलेशन हो रहे हैं, या PDF बन रही है — तो ऐसिंक जॉब इस्तेमाल करें ताकि ब्राउज़र रिक्वेस्ट खुला न रहे।
सबसे सरल फ्लो: पहले एक जॉब रिकॉर्ड बनाइए, भारी काम बैकग्राउंड में कीजिए, और जब फाइल तैयार हो जाए तो उपयोगकर्ता को डाउनलोड देने की अनुमति दीजिए। AppMaster में यह आमतौर पर ExportJob मॉडल (Data Designer) और एक बैकएंड Business Process द्वारा किया जाता है जो status, प्रगति फ़ील्ड और स्टोर्ड फाइल रेफरेंस को अपडेट करता है।
वास्तविक काम ट्रैक करें, समय नहीं। एक व्यावहारिक तरीका है step, processed_count, total_count (जब पता हो), और updated_at जैसी फ़ील्ड स्टोर करना, और UI उन फ़ील्ड्स को पोल करके साफ़ स्टेट दिखाए ताकि उपयोगकर्ता फंसा हुआ महसूस न करे और बार-बार एक्सपोर्ट न दबाएँ।
एक्सपोर्ट रिक्वेस्ट को idempotent बनाइए और जॉब रिकॉर्ड को सच्चाई का स्रोत रखिए। अगर उपयोगकर्ता फिर से क्लिक करता है, तो वही चल रही जॉब दिखाएँ (या समान फिल्टर के लिए डुप्लिकेट रोक दें) ताकि एक ही महंगे काम दो बार न चले।
राइट-इन-चंक्स: मेमोरी स्थिर रखने के लिए डेटा चंक्स में पढ़ें और लिखें। स्थिर पेजिंग के लिए निर्णायक सॉर्टिंग का उपयोग करें (उदाहरण: created_at फिर id) ताकि डेटा बदलते समय रिकॉर्ड मिस या डुप्लिकेट न हों।
जॉब शुरू होने पर एक स्नैपशॉट समय रिकॉर्ड करें और केवल उस समय तक के रिकॉर्ड्स एक्सपोर्ट करें ताकि आउटपुट रन के दौरान "हिले" नहीं। अगर कड़ाई चाहिए तो अपनी DB के सपोर्ट के अनुसार कांसिस्टेंट रीड या ट्रांजैक्शन रणनीति अपनाएँ, पर एक स्पष्ट स्नैपशॉट नियम शुरू करने के लिए काफी अच्छा है।
स्ट्रीमिंग तभी मदद करती है जब आप आउटपुट क्रम में बना सकते हैं और जल्दी से बाइट्स भेजना शुरू कर सकते हैं—यह बड़े CSV के लिए खासकर उपयोगी है। पर यह उन धीमे क्वेरीज को ठीक नहीं करती जो पहले बाइट से पहले ही मिनट्स ले रही हों; इसलिए स्ट्रीमिंग को पेजिंग के साथ जोड़कर उपयोग करें ताकि लगातार चंक्स लिखे जा सकें।
जैसे ही पंक्तियाँ तैयार हों, उन्हें लिखते जाएँ और CSV में उचित एस्केपिंग का पालन करें ताकि फ़ाइल Excel या अन्य टूल में टूटे नहीं। एन+1 लुकअप से बचें—रिलेटेड डेटा को पहले एक क्वेरी में लोड कर लें। एन्कोडिंग सामंजस्य में रखें (आम तौर पर UTF-8) और हेडर व कॉलम ऑर्डर स्थिर रखें।
PDF जनरेशन CPU-भारी होता है (लेआउट, फोंट, इमेजेस, पेज ब्रेक्स), इसलिए इसे बैकग्राउंड जॉब मानें और स्पष्ट सीमाएँ रखें। टेम्पलेट साधारण रखें, बड़े रिमोट इमेजेस से बचें, और प्रगति को सार्थक चरणों में रिपोर्ट करें ताकि उपयोगकर्ता जान सकें कि काम चल रहा है।


