एसिंक्रोनस फ़ंक्शन को फिर से आज़माएं

इस दस्तावेज़ में बताया गया है कि असिंक्रोनस (नॉन-एचटीटीपीएस) बैकग्राउंड फ़ंक्शन के लिए, अनुरोध कैसे किया जा सकता है, ताकि वे काम न करने पर फिर से कोशिश कर सकें.

इवेंट ट्रिगर होने पर काम करने वाले फ़ंक्शन पूरे क्यों नहीं होते

बहुत कम मामलों में, किसी आंतरिक गड़बड़ी की वजह से फ़ंक्शन समय से पहले बंद हो सकता है. साथ ही, डिफ़ॉल्ट रूप से फ़ंक्शन को अपने-आप फिर से शुरू किया जा सकता है या नहीं भी किया जा सकता.

आम तौर पर, इवेंट ट्रिगर होने पर काम करने वाला फ़ंक्शन, फ़ंक्शन कोड में मौजूद गड़बड़ियों की वजह से पूरा नहीं हो पाता. ऐसा इन वजहों से हो सकता है:

  • फ़ंक्शन में गड़बड़ी है और रनटाइम में अपवाद दिखता है.
  • फ़ंक्शन, किसी सेवा के एंडपॉइंट तक नहीं पहुंच सकता या ऐसा करने की कोशिश करते समय उसका समय खत्म हो जाता है.
  • फ़ंक्शन जान-बूझकर अपवाद दिखाता है. उदाहरण के लिए, जब कोई पैरामीटर पुष्टि नहीं कर पाता.
  • Node.js फ़ंक्शन, अस्वीकार किया गया प्रॉमिस दिखाता है या कॉलबैक को null के अलावा कोई दूसरी वैल्यू पास करता है.

ऊपर दिए गए किसी भी मामले में, फ़ंक्शन काम करना बंद कर देगा और गड़बड़ी का मैसेज दिखाएगा. मैसेज जनरेट करने वाले इवेंट ट्रिगर में फिर से कोशिश करने की नीतियां होती हैं. इन्हें अपने फ़ंक्शन की ज़रूरतों के हिसाब से बदला जा सकता है.

फिर से कोशिश करने की सिमैंटिक्स

Cloud Functions, इवेंट सोर्स से भेजे गए हर इवेंट के लिए, इवेंट-ड्रिवन फ़ंक्शन को कम से कम एक बार एक्ज़ीक्यूट करता है. फिर से कोशिश करने की सुविधा को कॉन्फ़िगर करने का तरीका, इस बात पर निर्भर करता है कि आपने फ़ंक्शन कैसे बनाया है:

  • Google Cloud Console या Cloud Run Admin API में बनाई गई फ़ंक्शन के लिए, आपको इवेंट ट्रिगर अलग से बनाने और मैनेज करने होंगे. ट्रिगर में फिर से कोशिश करने के डिफ़ॉल्ट तरीके होते हैं. इन्हें अपनी फ़ंक्शन की ज़रूरतों के हिसाब से बदला जा सकता है.
  • Cloud Functions v2 API की मदद से बनाए गए फ़ंक्शन, ज़रूरी इवेंट ट्रिगर अपने-आप बना देंगे. उदाहरण के लिए, Pub/Sub विषय या Eventarc ट्रिगर. डिफ़ॉल्ट रूप से, इन ट्रिगर के लिए फिर से कोशिश करने की सुविधा बंद होती है. Cloud Functions v2 API का इस्तेमाल करके, इसे फिर से चालू किया जा सकता है.

Cloud Run की मदद से बनाए गए इवेंट ट्रिगर होने पर काम करने वाले फ़ंक्शन

Google Cloud Console या Cloud Run Admin API में बनाई गई फ़ंक्शन के लिए, आपको इवेंट ट्रिगर अलग से बनाने और मैनेज करने होंगे. हमारा सुझाव है कि आप हर ट्रिगर टाइप के डिफ़ॉल्ट व्यवहार की समीक्षा करें:

Cloud Functions v2 API की मदद से बनाए गए इवेंट ट्रिगर होने पर काम करने वाले फ़ंक्शन

Cloud Functions v2 API का इस्तेमाल करके बनाए गए फ़ंक्शन. उदाहरण के लिए, Cloud Functions gcloud CLI, REST API या Terraform का इस्तेमाल करके बनाए गए फ़ंक्शन, आपके लिए इवेंट ट्रिगर बनाएंगे और उन्हें मैनेज करेंगे. डिफ़ॉल्ट रूप से, अगर किसी फ़ंक्शन को कॉल करने पर गड़बड़ी होती है, तो फ़ंक्शन को फिर से कॉल नहीं किया जाता और इवेंट को हटा दिया जाता है. इवेंट पर आधारित फ़ंक्शन के लिए, फिर से कोशिश करने की सुविधा चालू करने पर, Cloud Functions फ़ंक्शन को तब तक फिर से कॉल करता है, जब तक वह सफलतापूर्वक पूरा नहीं हो जाता या फिर से कोशिश करने की समयसीमा खत्म नहीं हो जाती.

किसी फ़ंक्शन के लिए, फिर से कोशिश करने की सुविधा डिफ़ॉल्ट रूप से चालू नहीं होती है. ऐसा होने पर, फ़ंक्शन हमेशा यह रिपोर्ट करता है कि वह सही तरीके से काम कर रहा है. साथ ही, इसके लॉग में 200 OK रिस्पॉन्स कोड दिख सकते हैं. फ़ंक्शन में कोई गड़बड़ी होने पर भी ऐसा होता है. यह साफ़ तौर पर बताने के लिए कि आपके फ़ंक्शन में कब गड़बड़ी हुई है, पक्का करें कि आपने गड़बड़ियों की जानकारी सही तरीके से दी हो.

फिर से कोशिश करने की सुविधा चालू या बंद करना

अपने फ़ंक्शन कोड से फिर से कोशिश करने की सुविधा कॉन्फ़िगर करना

Cloud Functions for Firebase की मदद से, किसी फ़ंक्शन के लिए कोड में फिर से कोशिश करने की सुविधा चालू की जा सकती है. functions.foo.onBar(myHandler); जैसे बैकग्राउंड फ़ंक्शन के लिए ऐसा करने के लिए, runWith का इस्तेमाल करें और फ़ेल होने से जुड़ी नीति कॉन्फ़िगर करें:

functions.runWith({failurePolicy: true}).foo.onBar(myHandler);

true को इस तरह से सेट करने पर, फ़ंक्शन को फिर से आज़माने के लिए कॉन्फ़िगर किया जाता है.

फिर से कोशिश करने की विंडो

दूसरी जनरेशन के फ़ंक्शन के लिए, फिर से कोशिश करने की यह विंडो 24 घंटे बाद खत्म हो जाती है. पहली जनरेशन के फ़ंक्शन के लिए, यह सात दिनों के बाद काम नहीं करता. Cloud Functions इवेंट ट्रिगर होने पर काम करने वाले नए फ़ंक्शन को फिर से आज़माता है. इसके लिए, वह एक्सपोनेंशियल बैकऑफ़ रणनीति का इस्तेमाल करता है. इसमें बैकऑफ़ का समय 10 से 600 सेकंड के बीच होता है. यह नीति, नए फ़ंक्शन पर पहली बार लागू होती है. यह बदलाव, उन मौजूदा फ़ंक्शन पर लागू नहीं होता जिन्हें इस रिलीज़ नोट में बताए गए बदलावों के लागू होने से पहले डिप्लॉय किया गया था. भले ही, आपने उन फ़ंक्शन को फिर से डिप्लॉय किया हो.

सबसे सही तरीके

इस सेक्शन में, फिर से कोशिश करने की सुविधा इस्तेमाल करने के सबसे सही तरीके बताए गए हैं.

कुछ समय के लिए होने वाली गड़बड़ियों को ठीक करने के लिए, फिर से कोशिश करने की सुविधा का इस्तेमाल करना

जब तक फ़ंक्शन ठीक से काम नहीं करता, तब तक उसे बार-बार आज़माया जाता है. इसलिए, यह ज़रूरी है कि आप फिर से कोशिश करने की सुविधा चालू करने से पहले, अपने कोड में मौजूद बग जैसी स्थायी गड़बड़ियों को टेस्ट करके ठीक कर लें. फिर से कोशिश करने की सुविधा का इस्तेमाल, कुछ समय के लिए होने वाली गड़बड़ियों को ठीक करने के लिए किया जाता है. इन गड़बड़ियों को फिर से कोशिश करने पर ठीक किया जा सकता है. जैसे, सेवा के ऐसे एंडपॉइंट जो कुछ समय के लिए काम नहीं करते या टाइम आउट हो जाते हैं.

अनंत बार कोशिश करने वाले लूप से बचने के लिए, खत्म होने की शर्त सेट करें

फिर से कोशिश करने की सुविधा का इस्तेमाल करते समय, अपने फ़ंक्शन को लगातार लूप होने से बचाना सबसे सही तरीका है. इसके लिए, फ़ंक्शन के प्रोसेस करना शुरू करने से पहले, खत्म होने की स्थिति को अच्छी तरह से तय करें. ध्यान दें कि यह तकनीक सिर्फ़ तब काम करती है, जब आपका फ़ंक्शन सही तरीके से शुरू हो और आखिरी शर्त का आकलन कर सके.

हालांकि, एक आसान और असरदार तरीका यह है कि टाइमस्टैंप वाले उन इवेंट को खारिज कर दिया जाए जो किसी तय समय से पुराने हैं. इससे, लगातार या उम्मीद से ज़्यादा समय तक गड़बड़ियां होने पर, बहुत ज़्यादा अनुरोधों को प्रोसेस करने से बचा जा सकता है.

उदाहरण के लिए, यह कोड स्निपेट 10 सेकंड से पुराने सभी इवेंट को खारिज कर देता है:

const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
  console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
  callback();
  return;
}

प्रॉमिस के साथ catch का इस्तेमाल करना

अगर आपके फ़ंक्शन में फिर से कोशिश करने की सुविधा चालू है, तो हैंडल न की गई कोई भी गड़बड़ी, फिर से कोशिश करने की सुविधा को ट्रिगर करेगी. पक्का करें कि आपका कोड ऐसी किसी भी गड़बड़ी को कैप्चर करता हो जिसकी वजह से फिर से कोशिश नहीं की जानी चाहिए.

यहां एक उदाहरण दिया गया है कि आपको क्या करना चाहिए:

return doFooAsync().catch((err) => {
    if (isFatal(err)) {
        console.error(`Fatal error ${err}`);
    }
    return Promise.reject(err);
});

इवेंट पर आधारित ऐसे फ़ंक्शन बनाना जिन्हें फिर से ट्रिगर किया जा सकता है और जो एक ही इनपुट के लिए एक ही आउटपुट देते हैं

इवेंट ट्रिगर होने पर काम करने वाले ऐसे फ़ंक्शन जिन्हें फिर से आज़माया जा सकता है, वे आइडेमपोटेंट होने चाहिए. यहां ऐसे फ़ंक्शन को आइडमपोटेंट बनाने के लिए, कुछ सामान्य दिशा-निर्देश दिए गए हैं:

  • कई बाहरी एपीआई (जैसे, Stripe) में, पैरामीटर के तौर पर idempotency key देने का विकल्प होता है. अगर ऐसे एपीआई का इस्तेमाल किया जा रहा है, तो आपको इवेंट आईडी को आईडंपोटेंसी की के तौर पर इस्तेमाल करना चाहिए.
  • आइटम को कम से कम एक बार डिलीवर करने की सुविधा के साथ, आइटम को एक ही बार प्रोसेस करने की सुविधा अच्छी तरह से काम करती है. ऐसा इसलिए, क्योंकि इससे फिर से कोशिश करना सुरक्षित हो जाता है. इसलिए, भरोसेमंद कोड लिखने का सबसे सही तरीका यह है कि आप फिर से कोशिश करने की सुविधा के साथ-साथ, एक ही कार्रवाई को कई बार करने की सुविधा को भी शामिल करें.
  • पक्का करें कि आपका कोड, इंटरनल तौर पर आइडमपोटेंट हो. उदाहरण के लिए:
    • पक्का करें कि नतीजे में बदलाव किए बिना, म्यूटेशन एक से ज़्यादा बार हो सकते हैं.
    • स्टेट में बदलाव करने से पहले, लेन-देन में डेटाबेस की स्थिति के बारे में क्वेरी करें.
    • पक्का करें कि सभी साइड इफ़ेक्ट, खुद ही आइडेमपोटेंट हों.
  • फ़ंक्शन के बाहर, कोड से अलग लेन-देन की जांच लागू करें. उदाहरण के लिए, किसी ऐसी जगह पर स्थिति को सेव करें जहां यह रिकॉर्ड किया गया हो कि दिए गए इवेंट आईडी को पहले ही प्रोसेस किया जा चुका है.
  • डुप्लीकेट फ़ंक्शन कॉल को आउट-ऑफ़-बैंड तरीके से मैनेज करें. उदाहरण के लिए, एक अलग क्लीन अप प्रोसेस बनाएं, जो फ़ंक्शन के डुप्लीकेट कॉल के बाद क्लीन अप करती है.

फिर से कोशिश करने की नीति को कॉन्फ़िगर करना

अपने फ़ंक्शन की ज़रूरतों के हिसाब से, सीधे तौर पर फिर से कोशिश करने की नीति को कॉन्फ़िगर किया जा सकता है. इससे आपको इनमें से किसी भी कॉम्बिनेशन को सेट अप करने में मदद मिलेगी:

  • फिर से कोशिश करने की अवधि को सात दिनों से घटाकर, कम से कम 10 मिनट कर दिया गया है.
  • एक्सपोनेंशियल बैकऑफ़ रीट्राय रणनीति के लिए, कम से कम और ज़्यादा से ज़्यादा बैकऑफ़ समय बदलें.
  • फिर से कोशिश करने की रणनीति को बदलकर, तुरंत फिर से कोशिश करने की रणनीति पर सेट करें.
  • डेड-लेटर विषय को कॉन्फ़िगर करें.
  • डिलीवरी की कोशिशों की ज़्यादा से ज़्यादा और कम से कम संख्या सेट करें.

फिर से कोशिश करने की नीति को कॉन्फ़िगर करने के लिए:

  1. एक एचटीटीपी फ़ंक्शन लिखें.
  2. Pub/Sub सदस्यता बनाने के लिए, Pub/Sub एपीआई का इस्तेमाल करें. साथ ही, फ़ंक्शन के यूआरएल को टारगेट के तौर पर सेट करें.

Pub/Sub को सीधे तौर पर कॉन्फ़िगर करने के बारे में ज़्यादा जानने के लिए, Pub/Sub फ़ेल होने की स्थिति को मैनेज करने से जुड़ा दस्तावेज़ देखें.