خطأ Backend 502/504 عند حفظ التعديلات الكبيرة على المنشورات الطويلة (~100 ألف كلمة) بسبب عنق الزجاجة في Diff

عند تحرير وحفظ منشورات طويلة للغاية (حوالي 100,000 حرف)، واجهنا مشكلة في تجاوز المهلة الزمنية للواجهة الخلفية (Backend Timeout). يصبح الخادم غير مستجيب أثناء عملية الحفظ، مما يؤدي إلى ظهور أخطاء 502/504. يعرض وحدة التحكم في الواجهة الأمامية مكدس الأخطاء التالي:

ajax-error.js:36:15
l ajax-error.js:36
u ajax-error.js:75
d ajax-error.js:84
Ember 41
update rest.js:72
update rest.js:72
save rest.js:115
editPost composer.js:1147
Ember 6

أجريت بعض الاختبارات المقارنة التي تشير إلى أن الاختناق يقع في حساب الفرق (Diff) بين النسخة القديمة والنسخة الجديدة:

  • يؤدي تحرير منشور طويل A مباشرة إلى منشور طويل B وحفظه باستمرار إلى حدوث تجاوز للمهلة الزمنية (أخطاء 502/504).
  • يؤدي مسح المنشور الطويل أولاً، وحفظ نص مؤقت قصير (مثلاً 5 أحرف)، ثم لصق المحتوى الجديد الكامل B وحفظه، إلى إتمام العملية بسرعة.

يبدو أن محرك حساب الفرق الحالي يواجه صعوبة في الحالات القصوى التي تتضمن نصوصاً طويلة جداً مع نسبة تغيير عالية. هل من الممكن إضافة آلية احتياطية للأداء؟ على سبيل المثال، عندما يكون النص طويلاً للغاية ونسبة التعديلات عالية، يمكن للنظام معاملته كـ “إعادة كتابة كاملة” بدلاً من إجراء حساب فرق مفصل سطراً بسطر.

هل لدى الفريق أي خطط لتحسين معالجة حساب الفرق للمنشورات الكبيرة، أو إدخال نوع من التدهور المتدرج / الحماية لمثل هذه السيناريوهات؟ فكرة أخرى هي السماح بنجاح الحفظ أولاً، ثم حساب الفرق بشكل غير متزامن لاحقاً.

إعجابَين (2)

في هذه الأثناء، سجلات يونيكورن على جانب الخادم التقطت النقطة الدقيقة للقطع، مؤكدةً أن العامل قُتل أثناء معالجة اختلاف النص المميز (markdown diff):

تلقي عامل يونيكورن إشارة USR2 تشير إلى أنه على وشك القطع، جاري إخراج تتبع المكدس (backtrace) للخيط الرئيسي
config/unicorn.conf.rb:204:in `backtrace'
config/unicorn.conf.rb:204:in `block (2 levels) in reload'
/var/www/discourse/lib/discourse_diff.rb:172:in `[]'
/var/www/discourse/lib/discourse_diff.rb:172:in `tokenize_markdown'
/var/www/discourse/lib/discourse_diff.rb:115:in `side_by_side_markdown'
/var/www/discourse/app/serializers/post_revision_serializer.rb:128:in `body_changes'
... 

هل يمكنني حل المشكلة المذكورة أعلاه عن طريق تغيير UNICORN_TIMEOUT إلى 60 أو 120؟

مرحبًا،

أعتقد أنني سأنقل هذا إلى Contribute > Bug. 100 ألف حرف أمر غير معتاد للغاية، ولكن بغض النظر، أعتقد أنه يجب تطبيق آلية بديلة ما.