يوضّح هذا المستند كيفية طلب إعادة محاولة تنفيذ الدوال في الخلفية غير المتزامنة (غير HTTPS) في حال تعذّر تنفيذها.
أسباب عدم اكتمال الدوال المستندة إلى الأحداث
في حالات نادرة، قد يتم إنهاء دالة قبل الأوان بسبب خطأ داخلي، وقد تتم إعادة محاولة تنفيذ الدالة تلقائيًا أو لا تتم تلقائيًا.
في العادة، قد يتعذّر إكمال دالة مستندة إلى الأحداث بنجاح بسبب أخطاء في رمز الدالة نفسه. وتشمل الأسباب المحتملة لذلك ما يلي:
- تحتوي الدالة على خطأ برمجي ويطرح وقت التشغيل استثناءً.
- لا يمكن للدالة الوصول إلى نقطة نهاية الخدمة، أو تنتهي مهلتها أثناء محاولة القيام بذلك.
- تطرح الدالة استثناءً عن قصد (على سبيل المثال، عندما يتعذّر التحقّق من صحة مَعلمة).
- تعرض دالة Node.js وعدًا مرفوضًا أو تمرّر قيمة غير
nullإلى دالة رد اتصال.
في أي من الحالات المذكورة أعلاه، ستتوقف الدالة عن التنفيذ وتعرض خطأ. تتضمّن مشغّلات الأحداث التي تنشئ الرسائل سياسات لإعادة المحاولة يمكنك تخصيصها لتلبية احتياجات الدالة.
دلالات إعادة المحاولة
توفّر Cloud Functions تنفيذًا لمرة واحدة على الأقل لدالة مستندة إلى الأحداث لكل حدث يصدر عن مصدر حدث. By default, if a function invocation terminates with an error, the function is not invoked again and the event is dropped. عند تفعيل عمليات إعادة المحاولة في دالة مستندة إلى الأحداث، Cloud Functionsتتم إعادة محاولة استدعاء الدالة التي تعذّر تنفيذها إلى أن تكتمل بنجاح أو تنتهي صلاحية نافذة إعادة المحاولة.
عندما لا تكون عمليات إعادة المحاولة مفعَّلة لدالة معيّنة، وهو الإعداد التلقائي، تُبلغ الدالة دائمًا بأنّها تم تنفيذها بنجاح، وقد تظهر رموز الاستجابة 200 OK في سجلّاتها. ويحدث ذلك حتى إذا واجهت الدالة خطأً. لتوضيح متى تواجه الدالة خطأ، تأكَّد من
الإبلاغ عن الأخطاء
بشكل مناسب.
ضبط عمليات إعادة المحاولة من رمز الدالة
باستخدام Cloud Functions for Firebase، يمكنك تفعيل عمليات إعادة المحاولة في الرمز البرمجي لدالة معيّنة. لتنفيذ ذلك لحدث في الخلفية، مثل إنشاء مستند Firestore جديد، اضبط خيار سياسة failurePolicy (الجيل الأول) أو retry (الجيل الثاني) على true:
الجيل الأول
exports.docCreated = functions
.runWith({
// retry on failure
failurePolicy: true,
})
.firestore.document("my-collection/{docId}")
.onCreate((change, context) => {
/* ... */
});
الجيل الثاني
const { onDocumentCreated } = require("firebase-functions/firestore");
exports.docCreated = onDocumentCreated(
{
// retry on failure
retry: true,
},
"my-collection/{docId}",
(event) => {
/* ... */
},
);
يؤدي ضبط true كما هو موضّح إلى ضبط دالة لإعادة المحاولة في حال تعذّر تنفيذها.
نافذة إعادة المحاولة
بالنسبة إلى دوال الجيل الثاني، تنتهي صلاحية نافذة إعادة المحاولة هذه بعد 24 ساعة. بالنسبة إلى دوال الجيل الأول، تنتهي صلاحيتها بعد 7 أيام. يعيد Cloud Functions محاولة تنفيذ الدوال المستندة إلى الأحداث التي تم إنشاؤها حديثًا باستخدام استراتيجية التراجع الأسي، مع تراجع متزايد يتراوح بين 10 و600 ثانية. يتم تطبيق هذه السياسة على الدوال الجديدة عند نشرها لأول مرة. ولا يتم تطبيقه بأثر رجعي على الدوال الحالية التي تم نشرها لأول مرة قبل سريان التغييرات الموضّحة في ملاحظة الإصدار هذه، حتى إذا أعدت نشر الدوال.أفضل الممارسات
يصف هذا القسم أفضل الممارسات لاستخدام عمليات إعادة المحاولة.
استخدام إعادة المحاولة لمعالجة الأخطاء المؤقتة
Because your function is retried continuously until successful execution, permanent errors like bugs should be eliminated from your code through testing before enabling retries. يُفضَّل استخدام عمليات إعادة المحاولة للتعامل مع حالات الفشل المتقطعة أو المؤقتة التي من المرجح أن يتم حلها عند إعادة المحاولة، مثل نقطة نهاية خدمة غير مستقرة أو مهلة.
ضبط شرط إنهاء لتجنُّب تكرار المحاولات بشكل لا نهائي
من أفضل الممارسات حماية الدالة من التكرار المستمر عند استخدام عمليات إعادة المحاولة. ويمكنك إجراء ذلك من خلال تضمين شرط نهاية محدّد جيدًا قبل أن تبدأ الدالة في المعالجة. يُرجى العِلم أنّ هذه الطريقة لا تنجح إلا إذا بدأت الدالة بنجاح وتمكّنت من تقييم شرط النهاية.
هناك طريقة بسيطة وفعّالة، وهي تجاهل الأحداث التي تحمل طوابع زمنية أقدم من وقت معيّن. يساعد ذلك في تجنُّب عمليات التنفيذ المفرطة عندما تكون حالات الفشل مستمرة أو أطول من المتوقع.
على سبيل المثال، يتجاهل مقتطف الرمز هذا جميع الأحداث التي مرّ عليها أكثر من 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 مع Promises
إذا كانت الدالة تتيح إعادة المحاولة، سيؤدي أي خطأ لم تتم معالجته إلى إعادة المحاولة. تأكَّد من أنّ الرمز البرمجي يرصد أي أخطاء لا يجب أن تؤدي إلى إعادة المحاولة.
في ما يلي مثال على ما يجب فعله:
return doFooAsync().catch((err) => {
if (isFatal(err)) {
console.error(`Fatal error ${err}`);
}
return Promise.reject(err);
});
جعل الدوال المستندة إلى الأحداث والقابلة لإعادة المحاولة متكررة
يجب أن تكون الدوال المستندة إلى الأحداث التي يمكن إعادة محاولة تنفيذها متكررة. في ما يلي بعض الإرشادات العامة لجعل هذه الدالة متكررة:
- تتيح لك العديد من واجهات برمجة التطبيقات الخارجية (مثل Stripe) تقديم مفتاح تكرار كمعلَمة. إذا كنت تستخدم واجهة برمجة تطبيقات من هذا النوع، يجب استخدام معرّف الحدث كمفتاح idempotency.
- تعمل ميزة "التحقّق من تكرار الطلب" بشكل جيد مع ميزة "التسليم مرة واحدة على الأقل"، لأنّها تجعل إعادة المحاولة آمنة. لذلك، من أفضل الممارسات العامة لكتابة رمز برمجي موثوق به هو الجمع بين العمليات المتكررة مع عمليات إعادة المحاولة.
- تأكَّد من أنّ الرمز البرمجي الخاص بك متكرر داخليًا. على سبيل المثال:
- تأكَّد من أنّ التغييرات يمكن أن تحدث أكثر من مرة بدون تغيير النتيجة.
- الاستعلام عن حالة قاعدة البيانات في معاملة قبل تغيير الحالة
- تأكَّد من أنّ جميع الآثار الجانبية هي نفسها غير قابلة للتكرار.
- فرض فحص المعاملات خارج الدالة، بشكل مستقل عن الرمز البرمجي على سبيل المثال، يمكنك الاحتفاظ بالحالة في مكان ما لتسجيل أنّه سبق أن تمت معالجة معرّف حدث معيّن.
- التعامل مع استدعاءات الدوال المكرّرة خارج النطاق على سبيل المثال، يمكنك استخدام عملية تنظيف منفصلة تزيل استدعاءات الدوال المكررة.
ضبط سياسة إعادة المحاولة
بناءً على احتياجات الدالة، قد تحتاج إلى ضبط سياسة إعادة المحاولة مباشرةً. سيسمح لك ذلك بإعداد أي مجموعة من الآتي:
- تقصير فترة إعادة المحاولة من 7 أيام إلى 10 دقائق فقط
- تغيير الحد الأدنى والحد الأقصى لوقت التراجع في استراتيجية إعادة المحاولة باستخدام التراجع الأسي
- غيِّر استراتيجية إعادة المحاولة إلى إعادة المحاولة فورًا.
- اضبط موضوعًا للرسائل غير الصالحة.
- اضبط الحدّ الأقصى والحدّ الأدنى لعدد محاولات التسليم.
لضبط سياسة إعادة المحاولة، اتّبِع الخطوات التالية:
- اكتب دالة HTTP.
- استخدِم واجهة برمجة التطبيقات Pub/Sub لإنشاء اشتراك في Pub/Sub، مع تحديد عنوان URL للدالة كهدف.
يمكنك الاطّلاع على مستندات Pub/Sub حول معالجة حالات التعطُّل لمزيد من المعلومات حول ضبط Pub/Sub مباشرةً.