يقدم دليل جديد متمحور حول Laravel للمطورين كيفية منع بوتات Telegram من انتهاء المهلة (timing out)، أو تكرار الإجراءات، أو الانهيار تحت ضغط العمل، وذلك عبر تأمين الـ webhook، واستخدام Redis لتحقيق خاصية idempotency، ونقل المهام الثقيلة إلى الطوابير (queues).
لماذا تحتاج webhooks الخاصة بـ Telegram إلى ما هو أكثر من مجرد مسار (route) بسيط
يرسل Telegram كل تفاعل للمستخدم إلى البوت كطلب HTTP POST إلى رابط (URL) يحدده المطور. تتوقع المنصة استجابة 200 OK في غضون ثوانٍ قليلة؛ وإذا استغرق الأمر أطول من ذلك، فستقوم بإعادة محاولة الطلب. تعني عمليات إعادة المحاولة أن نفس الـ update_id قد يصل عدة مرات، وإذا كان البوت يكتب في قاعدة بيانات أو يستدعي واجهات برمجة تطبيقات (APIs) خارجية داخل الطلب، فقد يؤدي ذلك إلى إنشاء صفوف مكررة، أو إرسال رسائل مزدوجة، أو حدوث حالات تسابق (race conditions). بالنسبة للبوتات التي تتعامل مع عشرات أو مئات الرسائل في الثانية، يصبح هذا التأخير عائقاً سريعاً.
1. تأمين نقطة النهاية (endpoint) باستخدام ترويسة سرية (secret header)
يضيف Telegram ترويسة X-Telegram-Bot-Api-Secret-Token إلى كل استدعاء للـ webhook. قم بمقارنة هذه الترويسة بقيمة سرية مخزنة على الخادم — باستخدام دالة hash_equals في PHP لتجنب هجمات التوقيت (timing attacks) — وارفض أي طلب لا يأتي من Telegram. في Laravel، ضع هذا التحقق في middleware بحيث يتم التحقق قبل أن يصل الـ controller إلى الحمولة (payload).
2. جعل كل تحديث idempotent باستخدام Redis
تحمل كل حمولة واردة update_id فريداً. يقترح الدليل كتابة هذا المعرف في Redis باستخدام علم NX (التعيين في حال عدم الوجود). تنجح العملية فقط في المرة الأولى؛ أما عند إعادة المحاولة، فسيجد النظام أن المفتاح موجود بالفعل، ويمكن للـ webhook أن يعيد استجابة 200 OK فوراً، مما يشير إلى Telegram بأن التحديث قد تمت معالجته. ولأن Redis يعمل في الذاكرة (in-memory)، فإن عملية التحقق لا تضيف أي تأخير تقريباً، ويظل المفتاح موجوداً للكشف عن التكرارات.
3. إسناد المهام الثقيلة إلى وظائف الخلفية (background jobs)
حتى مع وجود فحص سريع في Redis، يجب ألا يتم تشغيل منطق العمل الخاص بالبوت (business logic) — مثل الكتابة في قاعدة البيانات، أو استدعاءات API الخارجية، أو صياغة الرسائل — داخل طلب الـ webhook. قم بإرسال وظيفة في طابور Laravel (queued job) بمجرد التحقق من الـ webhook وتخزين الـ update_id. أرسل استجابة HTTP فوراً، واترك الـ worker يعالج الوظيفة بالسرعة التي تناسبه. هذا يبقي البوت ضمن المهلة الزمنية المحددة لاستجابة Telegram ويمنع المنصة من إعادة المحاولة.
تحسينات لمستوى الإنتاج (Production-grade)
- احترام حدود المعدل (rate limits). يعيد Telegram رمز الاستجابة 429 Too Many Requests مع ترويسة
Retry-Afterعندما يتجاوز البوت الحدود المسموح بها في الثانية. يجب على عمال الطابور (queue workers) قراءة هذه الترويسة والتوقف مؤقتاً قبل إعادة محاولة الوظيفة الفاشلة. - احفظ البيانات قبل الرد. قم بكتابة أي بيانات للمستخدم في قاعدة البيانات أولاً؛ وفقط بعد إتمام العملية (commit) بنجاح، يجب على البوت إرسال رسالة تأكيد. هذا الترتيب يتجنب السيناريوهات التي تصل فيها الرسالة إلى المستخدم ولكن السجل المقابل لها لا يتم إنشاؤه أبداً.
- تقليص حمولات الـ callback. يضع Telegram حداً أقصى لـ
callback_dataيبلغ 64 بايت. قم بتخزين البيانات الكبيرة (blobs) في قاعدة البيانات ومرر فقط معرفاً مرجعياً (reference ID) في حمولة الزر للبقاء ضمن الحد المسموح به.
الخلاصة: إن توثيق الطلب، ومنع التكرار باستخدام Redis، وتفريغ العمل إلى الطوابير، يتيح لمطوري Laravel بناء بوتات Telegram تستجيب فوراً، وتلتزم بحدود المعدل، وتتوسع بسلاسة مع زيادة طلب المستخدمين.
