كيف بُنيت الواجهة الخلفية لـ NDDev: Rust وقاعدة بيانات واحدة ووكيل بدل لوحة الإدارة
تعمل مواقع NDDev الستة بخمس لغات، ونماذج الطلبات وحجز الاجتماعات والمساعد ونشر المواد، كلها على نواة واحدة. نعرض هنا القرارات التي بُنيت عليها وأسباب اتخاذها.
نظام أحادي معياري بلغة Rust
النواة مساحة عمل Cargo واحدة من ثلاث طبقات. تصف domain القواعد دون إدخال أو إخراج: ما المراجعة والنشر والطلب، وما انتقالات الحالة المسموح بها. وتتولى infrastructure قاعدة PostgreSQL والخدمات الخارجية. وتوفّر api واجهات HTTP وسطر الأوامر وMCP. أما تحسين محركات البحث والمراقبة فخدمتان منفصلتان بلغة Rust لكل منهما قاعدة بيانات خاصة، لأن وتيرة تغيّرهما وأنماط أعطالهما مختلفة.
التقنيات: Rust 1.99 وTokio وaxum وSQLx وPostgreSQL. والمعرّفات من نوع UUIDv7: يولّدها التطبيق وتُرتَّب حسب وقت الإنشاء.
وكيل بدل لوحة الإدارة
لا تملك المنصة نظام إدارة محتوى مرئيًا. يديرها بالأوامر المالك والوكلاء العاملون لحساب الشركة: سطر الأوامر وواجهة HTTP وMCP تستدعي طبقة الأوامر نفسها. كل أمر محدد الأنواع، يتحقق من الصلاحيات ويقبل مفتاح عدم التكرار، فإعادة الطلب بالمفتاح نفسه تعيد النتيجة السابقة بدل إنشاء نسخة مكررة. ويحدد التعديل نسخة المستند المتوقعة: فإن تغيّر المستند في الأثناء رفض الأمر بدل أن يكتب فوق عمل غيره بصمت.
حتى بيانات الاتصال ونصوص المواقع ليست ثوابت في الشيفرة، بل مراجعات في قاعدة البيانات تُغيَّر بأمر وتُنشر مع المحتوى.
قاعدة بيانات واحدة ومهام خلفية موثوقة
تعيش الحالة كلها في PostgreSQL. والعمل الخلفي — تحسين البحث والترجمات وبناء المواقع والبريد — مهام في القاعدة نفسها: صندوق صادر وصندوق وارد، واستئجار المهام برموز fencing، ومعاملات قصيرة. لا حاجة إلى وسيط رسائل منفصل لهذا الحمل. ولا نعد بتنفيذ التأثيرات الخارجية مرة واحدة بالضبط: تُقبل نتيجة الخدمة الخارجية فقط إذا كانت تجيب عن عمل طُلب فعلًا وعلى مجموعة البيانات المصدرية نفسها.
المراجعات والنشر كلقطة
ينشئ كل تعديل مراجعة جديدة غير قابلة للتغيير. ويجمع النشر حزمة من مراجعات محددة ومخرجات تحسين البحث الخاصة بها ويمنحها رقم جيل. تُبنى المواقع من بيان هذه الحزمة، فإعادة البناء تنتج الصفحات نفسها. ولاستعادة نسخة سابقة من صفحة يكفي نشر مراجعتها السابقة، فهي لا تزال محفوظة.
تحسين البحث خدمة منفصلة
تطلب كل مراجعة قابلة للفهرسة عمل تحسين البحث من خدمة منفصلة. يقترح النموذج العنوان والوصف، ويطابقهما طلب محرّر منفصل مع النص المصدر، وتتحقق Rust من الاقتباسات وشكل المقتطف وخلوّه من أسعار ومقاييس مختلقة. أما الروابط الأساسية وقواعد robots وhreflang وترميز schema.org فتُبنى بشكل حتمي. وإذا تعذّر الوصول إلى النموذج وُسمت النتيجة بصدق على أنها احتياطية، ولا تُنشر إلا بقرار صريح.
واجهة أمامية تحت رقابة الناشر
الواجهة الأمامية مستودع منفصل مبني بـ Astro. يبنيها ناشر النواة داخل بيئة معزولة: مساحات أسماء Linux معزولة وLandlock، دون شبكة ودون وصول إلى الأسرار. يقيس الناشر الناتج بنفسه ثم ينشره على المواقع، وتعود النسخة السابقة من الواجهة بأمر واحد.
البيانات والتأخير
تكتب النواة في أمستردام، وتعمل نسخة متزامنة من قاعدة البيانات في كازاخستان. قسنا البديل: نقل الكتابة إلى كازاخستان مع إبقاء الواجهة البرمجية في أمستردام يجعل كل استعلام يعبر خطًا بتأخير نحو 90 ملّي ثانية. كان إرسال الطلب سيرتفع من 119 ملّي ثانية إلى 2.58 ثانية، وفتح الكتالوج من 61 إلى 558 ملّي ثانية، والبحث من 55 إلى 929 ملّي ثانية. أما النسخة المتزامنة فتكلّف رحلة ذهاب وإياب واحدة لكل التزام.
المراقبة
تُرسَل التتبعات والمقاييس بصيغة OpenTelemetry، لكن عمل النواة لا يعتمد على المستقبِل: المخازن المؤقتة محدودة، وإذا تعذّر الجمع تستمر خدمة الطلبات.
ماذا يعني ذلك لمشاريع العملاء
لا ننقل هذه البنية كاملة إلى كل مشروع، فالموقع الصغير لا يحتاج إليها. لكننا نطبّق بضع قواعد في كل مكان: عقود صريحة بين أجزاء النظام، وتغييرات لا يمكن أن تضيع أو تُطبَّق مرتين، وسلوك قابل للقياس في بيئة التشغيل، وعودة إلى النسخة السابقة دون تعديل البيانات يدويًا.