تشخيص أخطاء "buffering timed out" في Mongoose — دليل عملي
دليل واضح خطوة بخطوة لمعالجة الخطأ MongooseError: Operation buffering timed out، مع أمثلة واقعية، وأوامر جاهزة للنسخ، وتوصيات آمنة للإنتاج لتطبيقات Node.js + MongoDB.
نظرة عامة
إذا كان تطبيق Node.js الذي يستخدم Mongoose يعرض خطأ مثل:
MongooseError: Operation profiles.findOne() buffering timed out after 10000ms
فهذا يعني أن Mongoose حاول تنفيذ استعلام قبل توفر اتصال مستقر مع MongoDB، ثم توقف بعد انتهاء مدة الانتظار.
هذا المقال يقدّم قائمة عملية قابلة للتكرار لتشخيص المشكلة وحلها، ويشرح سبب حدوثها، ويعرض أنماطاً جاهزة للإنتاج لمنع تكرارها.
من المستفيد من هذا الدليل
- مطورو Backend الذين يستخدمون Node.js + Mongoose محلياً، داخل Docker، أو في بيئة الإنتاج.
- المطورون الذين ينشرون تطبيقاتهم على VPS أو السحابة (بما في ذلك قواعد البيانات المُدارة مثل Atlas).
- الفرق التي تبني تطبيقات أعمال حيث يؤدي التوقف أو فشل الاستعلامات إلى تعطّل المستخدمين.
لماذا يحدث هذا الخطأ؟ (شرح مبسّط)
يقوم Mongoose بتخزين الاستعلامات مؤقتاً (buffering) إذا لم يكن برنامج تشغيل MongoDB قد أنهى الاتصال بعد. هذا يسمح للتطبيق باستدعاء النماذج قبل وجود اتصال فعلي، ولكن إذا لم يصبح الاتصال جاهزاً خلال المهلة المحددة (الافتراضي 10 ثوانٍ في كثير من الإعدادات)، فسيتم رمي خطأ مهلة زمنية.
الأسباب الشائعة:
- خادم MongoDB غير قيد التشغيل.
- سلسلة اتصال غير صحيحة (المضيف، المنفذ، اسم قاعدة البيانات، أو بيانات الدخول).
- حظر شبكي أو جدار ناري (المنفذ مغلق أو IP غير مسموح به).
- مشاكل DNS أو اكتشاف الكلاستر (خصوصاً مع Atlas دون إعداد SRV صحيح).
- غياب الأمر
mongodمن PATH في النظام. - ضغط عالي على الخادم أو بطء في التخزين.
قائمة فحص سريعة (ابدأ من هنا)
- تأكد أن خادم MongoDB يعمل على المضيف المتوقع.
- تحقق من صحة MongoDB URI في التطبيق.
- جرّب الاتصال يدوياً باستخدام
mongoshأوmongo. - في قواعد البيانات السحابية، تحقق من IP allowlist ونوع الاتصال.
- راجع إعدادات الاتصال في Mongoose وفكّر بزيادة
serverSelectionTimeoutMS. - فعّل تسجيل أحداث الاتصال في Mongoose.
استكشاف الأخطاء خطوة بخطوة
1. التحقق من سلسلة الاتصال
mongodb://localhost:27017/yourdbname
```
mongodb+srv://user:pass@cluster0.xxxxx.mongodb.net/yourdbname?retryWrites=true&w=majority تأكد من صحة القيم، وإذا كانت مأخوذة من متغيرات بيئة، اطبعها (مع إخفاء كلمات المرور).
```2. التأكد من أن MongoDB يعمل
sudo systemctl status mongod
```
sudo systemctl start mongod
sudo journalctl -u mongod --no-pager | tail -n 200 إذا لم يكن الأمر mongod موجوداً، يجب تثبيت MongoDB أو إضافته إلى PATH.
3. تجربة اتصال يدوي
mongosh "mongodb://localhost:27017/yourdbname"
إذا فشل الاتصال اليدوي، فالمشكلة بيئية (شبكة، صلاحيات، أو توقف الخادم).
4. التحقق من المنفذ
ss -plnt | grep 27017
5. في حالة Docker
- تأكد أن الحاويات على نفس الشبكة.
- لا تستخدم
localhostإذا كانت قاعدة البيانات في حاوية أخرى.
6. إعدادات Atlas
- أضف IP الخادم إلى allowlist.
- استخدم صيغة الاتصال الصحيحة (+srv).
7. زيادة المهلات الزمنية
mongoose.connect(process.env.MONGODB_URI, {
```
serverSelectionTimeoutMS: 30000,
connectTimeoutMS: 30000,
socketTimeoutMS: 45000
});
```
8. تعطيل التخزين المؤقت إذا رغبت
mongoose.set('bufferCommands', false);
9. تسجيل أحداث الاتصال
mongoose.connection.on('connected', () => console.log('connected'));
أفضل ممارسات الإنتاج
- الفشل السريع: لا تستقبل الطلبات قبل نجاح الاتصال.
- إعادة المحاولة بتدرّج: استخدم exponential backoff.
- إغلاق سلس: أغلق الاتصال عند SIGINT/SIGTERM.
- Health checks: أنشئ endpoint يتحقق من جاهزية قاعدة البيانات.
- المراقبة: راقب زمن الاستجابة وعدد الاتصالات.
الخلاصة
خطأ buffering timed out هو مؤشر على فشل الاتصال ضمن المهلة المحددة.
باتباع الخطوات السابقة والتحقق المنهجي من الإعدادات والبيئة، يمكن حل معظم الحالات الواقعية.
دمج هذه الخطوات مع ممارسات الإنتاج سيجعل تطبيقك أكثر استقراراً وقابلية للصيانة.
