مؤخراً أصبحت المسؤول الإداري والصائن الوحيد لمثيل صورة Docker أساسي لـ Discourse تم تثبيته في الأصل على خادمنا في عام 2021 (أعتقد) وتم تحديثه بشكل أساسي بواسطة شخص آخر. منذ فترة، ربما منذ البداية، كنا نواجه مشكلة في تحميلات المنشورات المحذوفة برفق لا يتم تحويلها إلى ملفات يتيمة وتنظيفها، وقد كنت أحاول استكشاف هذه المشكلة مرة أخرى لبضعة أيام حيث تتراكم الملفات القديمة باستمرار وتستهلك مساحة التخزين. نحن لا نستخدم S3 وهناك مساحة تخزين كافية للتحميلات التي نريد الاحتفاظ بها بالفعل.
لقد قمت بترحيل ملف النسخ الاحتياطي الكامل لـ Discourse بما في ذلك التحميلات إلى خادم اختبار منفصل للاختبار عن طريق إعادة البناء باستخدام app.yml الخاص بنا باتباع أدلة تثبيت Discourse Docker الرسمية وبعد ذلك استعادة النسخ الاحتياطي من سطر الأوامر. يبدو أن كلا التثبيتين يعملان بشكل متطابق وبدون مشاكل واضحة أخرى، لكن مشكلة التحميل لا تزال قائمة.
لا يبدو أنني أجد أي أخطاء ذات صلة في أي سجلات، و Sidekiq يقوم بتشغيل وظائف التنظيف كما هو مجدول. لقد قمت بتشغيل rake db:migrate على إصدار الاختبار وأعدت البناء عدة مرات، وحاولت حذف المنشورات بشكل دائم والتحقق من الإعدادات. بعد حذف بعض المنشورات بشكل دائم مباشرة من وحدة تحكم rails ومحاولة تشغيل وظيفة التنظيف يدويًا، لاحظت أن دليل tombstone قد زاد حجمه قليلاً في وقت ما وكانت هناك بعض الملفات في البداية على أي حال، لذا يجب أن تكون الآلية قد عملت في بعض الحالات، أليس كذلك؟ بالنظر إلى الزيادة الصغيرة في الحجم، لا تزال الغالبية العظمى من الملفات القديمة غير مكتشفة كملفات يتيمة.
الإعدادات الحالية ذات الصلة في لوحة الإدارة مدرجة أدناه. هل يمكنني تعيين الإعدادات الأخيرة إلى 0 لتجاوز فترات السماح فعليًا أثناء الاختبار؟
تنظيف التحميلات = صحيح
فترة سماح تنظيف التحميلات اليتيمة بالساعات = 1
فترة سماح حذف التحميلات المحذوفة بالأيام = 1
كيف يمكنني استكشاف هذه المشكلة بكفاءة؟ أنا مرتاح لاستخدام سطر الأوامر ولكن مهاراتي في قواعد البيانات أساسية، لذا سأكون ممتنًا جدًا لبعض النصائح لتجنب المرور عبر كل تفاصيل إعداد الخادم الممكنة دون معرفة ما أبحث عنه في هذه المرحلة.
لقد كنت أبحث وأقرأ هذا المنتدى بيأس عن حالات مماثلة، ولكن هناك عدد قليل فقط ويبدو أن تلك المواضيع تتوقف إما عند طريق مسدود أو حلول يدوية لملفات فردية، لذا فهي ليست مناسبة بشكل مباشر لحالة الاستخدام هذه.
يرجى مطالبتي بمزيد من التفاصيل إذا لزم الأمر، أنا أبذل قصارى جهدي لحل هذه المشكلة بشكل دائم.
أصبحت تلك المواضيع وبعض المواضيع الأخرى المرتبطة بها مألوفة جدًا بالنسبة لي أثناء محاولة حل هذه المشكلة، ولكن للأسف لم تقدم أي حلول نهائية لهذه المشكلة.
بالأمس على الخادم التجريبي، قمت بتشغيل هذه الأوامر المعدلة للمواضيع والمنشورات المحذوفة منذ أكثر من 9 أيام:
بعد ذلك، لاحظت زيادة طفيفة في حجم محتوى دليل الأحجار التذكارية وما زلت أراقب الوضع بسبب فترة السماح، وما زلت أتساءل عما إذا كان تغيير الإعدادات ذات الصلة إلى صفر ساعات/أيام سيتجاوز وقت الانتظار أثناء الاختبار.
في وقت سابق على الخادم الأصلي، حاولت إزالة التحميلات من أحدث مراجعات المنشورات، لكن الملفات كانت لا تزال متاحة بعد فترة السماح.
في هذه المرحلة، سأكون شخصيًا سعيدًا جدًا بمعرفة أي حل يدوي فعال لحذف موضوع واحد نهائيًا مع منشوراته وتحميلاته غير المشار إليها في أي مكان آخر، ولكن قد تكون هذه مشكلة كبيرة لأشخاص آخرين يديرون Discourse بشكل طبيعي بافتراض أن إعدادات التنظيف في لوحة الإدارة ستكون فعالة كما هو موضح ولكن ليس بالضرورة ملاحظة ما إذا كان الأمر ليس كذلك وينتهي بهم الأمر بتحميلات حساسة يحتمل أن تكون قد تم حذفها نهائيًا ولكنها في الواقع تبقى في نظام الملفات. مشكلتنا لحسن الحظ تتعلق فقط بالتخزين الضائع، ولكن بالنسبة لشخص آخر قد يكون هذا أسوأ بكثير.
هناك ذكر آخر مشابه قبل شهرين فقط:
إذن، أي نصائح حول كيفية معرفة ما إذا كان هذا خطأ في التكوين من جانبنا أم خطأ فعلي؟ لقد كنا سعداء جدًا بـ Discourse بخلاف ذلك وأنا متحمس جدًا لحل هذه المشكلة ومساعدة الآخرين على طول الطريق.
هذا مجرد تخمين ولكنه من خلال نظرة سريعة على نماذج post و post_upload و upload، يمكنك على الأرجح اكتشاف ما إذا كان لديك تحميلات يتيمة (كائنات قاعدة بيانات) باستخدام هذا:
Upload.find_by_sql("select * from uploads where id in (select upload_id from post_uploads where post_id not in (select id from posts))")
لم أختبر ذلك لذا لا يمكنني التأكد مما إذا كان سيجد التحميلات اليتيمة بشكل صحيح أو حتى ينفذ دون خطأ. في حال لم ينجح كما هو الحال وقد يتمكن شخص آخر من جعله يعمل، وكذلك فقط لأي شخص آخر مهتم، سأقوم بتقسيم الغرض.
Upload.find_by_sql() تُرجع مجموعة من كائنات Upload التي تتطابق مع استعلام SQL المقدم.
(select id from posts) يحصل على جميع معرفات المنشورات الموجودة.
(select upload_id from post_uploads where post_id not in () يحصل على جميع معرفات تحميلات المنشورات التي لا يوجد لها منشور.
select * from uploads where id in () يحصل على جميع التحميلات التي تطابق معرفات تحميلات المنشورات هذه.
هذا مجرد طريق واحد محتمل للتحقيق، للأسف لا أعرف نظام التحميل جيدًا لأساهم كثيرًا بخلاف ذلك، باستثناء القول بأن ما سبق بالتأكيد لا يأخذ في الاعتبار جميع المواقف. المنشورات المعدلة بدلاً من المحذوفة هي مثال واضح.
هناك أيضًا أنواع أخرى من التحميلات غير مأخوذة في الاعتبار مثل تحميلات المستخدم التي أفترض أنها أشياء مثل تحميل صورة ملف شخصي.
يمكن للمكونات الإضافية أيضًا إنشاء التحميلات والاحتفاظ بها، لا أعرف ما يحدث معها إذا تمت إزالة المكون الإضافي مثلاً. أعتقد أن بيانات المكون الإضافي تبقى في قاعدة البيانات بعد إزالة المكون الإضافي مما يعني أن أي تحميلات تم إنشاؤها بواسطة هذا المكون الإضافي لا تتم إزالتها أبدًا في هذا الموقف.
الاستعلام يعمل ولكنه يسرد فقط تحميلين وتفاصيلهما. يجب أن يكون هناك مئات أو آلاف التحميلات التي تطابق معايير اليتيم، ومعظمها ملفات صور تم تحميلها في الأصل بواسطة المستخدمين أثناء إنشاء منشورات عادية.
كان هناك نوع من التحديث الشامل لعملية التحميل بعد فترة من تثبيتنا الأصلي، وأتساءل عما إذا كان ذلك قد يتعلق بوضعنا الحالي بطريقة ما: A new era for file uploads in Discourse
كانت فترة السماح قد انتهت على خادم الاختبار التجريبي بحلول الآن، ولكني لا أرى أي تأثير في حجم دليل التحميل ولا تزال الملفات التجريبية متاحة. ما الذي يجب أن أبحث عنه بعد ذلك؟ هل يمكن أن يكون هذا ناتجًا عن بعض أذونات نظام الملفات الخاطئة أو ما شابه، هل هناك طريقة سهلة للتحقق؟ لقد نفدت أفكاري للأهداف المحددة، كل شيء آخر يعمل بشكل رائع وهذه هي المشكلة الوحيدة التي نواجهها حاليًا.
جارٍ البحث في مواضيع مشابهة لجمع الحالات التي لم يتم حلها والتي قد تتطابق، إليك مثال جيد على كيف يمكن لهذه المواقف أن تسبب مشاكل قانونية بسبب تحميلات المستخدمين التي لا يتم التخلي عنها وإزالتها بشكل دائم كما ينبغي:
موقف آخر مشابه يعود تاريخه إلى عام 2016:
هذه الأنواع من الظروف تخلق فجوة كبيرة للإساءة وحتى الهجمات المستهدفة لتحميل محتوى غير قانوني قد لا تتم إزالته بشكل دائم من الخادم حتى عندما يفترض المسؤولون ذلك. بالطبع، يمكن حذف الملفات الفردية يدويًا مباشرة من نظام الملفات، لكنني لا أعتقد أنه يجب إجبار الأشخاص على سلوك هذا الطريق لحاجة أساسية جدًا، خاصة عندما يكون هناك إعداد واجهة مستخدم رسومية يشير إلى عملية تطهير تلقائية وغالبًا ما لا يمتلك المشرفون وصولاً مباشرًا إلى الخادم على أي حال. كما أن الحذف اليدوي غير عملي مع أطنان من الملفات المتناثرة في مواضيع مختلفة محذوفة.
هل هناك أساس كافٍ لتقرير خطأ فعلي؟ ما زلت لا أستبعد احتمالية سوء التكوين من جانبنا، لكنني في حيرة من أمري بسبب نقص رسائل الخطأ وكل شيء آخر يبدو أنه يعمل بشكل جيد. لقد أمضيت عددًا متزايدًا من الأيام في استكشاف الأخطاء وإصلاحها والاختبار، واكتسبت المزيد من المعرفة حول Discourse ومكوناته في هذه العملية، لذلك أعتقد أنه مع بعض التوجيه يمكنني المساعدة في تحديد ما إذا كانت هناك تفاصيل حالة زاوية معينة تثير هذا السلوك الغريب. آمل أن يكون من المقبول الإشارة إلى @zogstrip في هذه المرحلة؟
كحل مؤقت، هل من الممكن نقل جميع التحميلات يدويًا إلى دليل المهملات واستخدام طرق استعادة التحميل لاستعادة الملفات غير اليتيمة فقط إلى مجلداتها الصحيحة؟ لقد حاولت بالفعل القيام بذلك اليوم، لكن rake uploads:recover_from_tombstone لم تستعد أي ملفات. هل يمكن أن يشير هذا إلى مشكلة أكبر في إدخالات قاعدة بيانات التحميلات؟
مرحباً. أواجه نفس المشكلة أو مشكلة مشابهة، لا أستطيع معرفة سبب عدم حذف الملفات. هل يواجه أي شخص آخر هذه المشكلة حتى الآن؟
لقد قمت بتشغيل بعض استعلامات SQL ويبدو أن المراجع “العالقة” للتحميلات كلها مسودات (Drafts)، لكنني تحققت من مسوداتي ومسودات المستخدمين الآخرين ولا يوجد أي منها. جداول المسودات فارغة.
تم تمكين تنظيف اليتيم (orphan cleaning) وتم تعيين الإعدادات لحذف اليتيم بأسرع ما يمكن.
لقد أرفقت استعلام SQL.
SELECT
uploads.original_filename,
ROUND(uploads.filesize / 1000000.0, 2) AS size_in_mb,
uploads.extension,
uploads.created_at,
uploads.url,
upload_references.upload_id,
upload_references.target_id,
upload_references.target_type,
upload_references.created_at,
upload_references.updated_at
FROM upload_references
JOIN uploads ON uploads.id = upload_references.upload_id
ORDER BY uploads.filesize DESC
LIMIT 250
يحدث هذا منذ أن قمت بتثبيت المنتدى. حتى عندما لم تكن هناك سمات مخصصة أو إضافات مثبتة.
حتى شعار المنتدى القديم الذي قمت بتحميله عدة مرات (أول ملف تم تحميله على الإطلاق) لا يزال يُشار إليه كمسودة ولا يزال في مجلد التحميلات.
نظريًا، يمكنني تصفية جميع مراجع التحميل وتصفيتها للمسودات حسب نوع الهدف (target_type)، ثم الحذف من قاعدة البيانات… والسماح لمهام sidekiq بالتعامل مع التنظيف (هل أنا على حق؟)
لكنني أستخدم نسخة مستضافة ذاتيًا وأنا جديد جدًا على Discourse، لذلك من الأفضل أن أسأل هنا…
سيكون هذا حلاً بديلاً، ولكن لا يزال هناك سؤال - لماذا يحدث هذا؟
آمل أن يكون لدى شخص ما بعض الاقتراحات، مساحة القرص لدي تنمو بشكل كبير
أود حقًا حلها بطريقة ما، فمنتدياتنا تتلقى الكثير من التحميلات ولكن جزءًا صغيرًا فقط منها يحتاج إلى الاحتفاظ به على المدى الطويل، لذا يتم إهدار الكثير من مساحة القرص. أي اقتراحات لاستكشاف الأخطاء وإصلاحها محل تقدير.
لقد قمت بتثبيت المنتدى قبل أسبوعين وتوجد به هذه المشكلة منذ البداية. يبدو أنها خطأ ما.
هل يمكنك تشغيل نفس استعلام SQL والتحقق مما إذا كانت هناك الكثير من الإشارات العالقة لـ “المسودات”؟ من السهل رؤيتها، لدي العشرات منها ولكن في جدول المسودات يوجد مسودتان أو ثلاث مسودات حقيقية. يبدو أنها لا تُحذف بعد التحرير (لا تكون مسودة بعد الآن، ولكن تظل الإشارة في قاعدة البيانات في كل مرة يتم فيها تحرير منشور على سبيل المثال).
أحتاج إلى معرفة كيفية حذف إدخال مرجعي من قاعدة البيانات وحذف الإشارات لملف واحد أولاً، ثم التحقق مما إذا كانت مهمة التنظيف تعمل.
لا أعرف مدى أمان القيام بذلك، ولكن هذه الإدخالات غير المحدودة للمسودات تبدو خاطئة بالنسبة لي.
يمكنني تقديم السجلات للموظفين/المطورين، أنا فقط جديد على Discourse ولا أعرف أي ملفات سجل ستساعد.
تحرير:
أحاول فهم بنية قاعدة البيانات، وهل يمكنني حذف إدخالات التحميل هذه دون مشاكل أخرى (لا أريد أن أفوت بعض علاقات قاعدة البيانات المهمة). أيضًا، لا أفهم ما هي تسلسلات المسودات بالضبط.
لكن يجب عليّ مضاعفة منتدى الإنتاج الخاص بي إلى جهاز افتراضي محلي، عندها فقط يمكنني الاختبار…
موضوع آخر ذو صلة، لقد نشرت هناك لأنني لم أكن على علم بهذا الموضوع.
أعتقد أن الطريقة الوحيدة لحذف صورة بطريقة تلقائية هي تعديلها يدويًا قبل حذفها. لكنني لست متأكدًا تمامًا من أن هذا يعمل أيضًا. أستخدم إعدادات مطابقة تمامًا لإعداداتك فيما يتعلق بالتنقية (لكنني أستخدم تخزينًا متوافقًا مع S3) ويمكنني أيضًا التأكيد على أن الصور لا يتم تنقيتها أبدًا إذا تم حذف المنشور الوحيد الذي يحتوي على هذه الصورة (يمكن أن تحتوي عدة منشورات على نفس الصورة، ويفترض أن تكون صور الأفاتار وشعارات المستخدم أيضًا).
أستخدم هذا الحل للبحث لمعرفة ما إذا كانت الصورة مستخدمة في منشورات إضافية، والذي قدمه @RGJ
سيكون من الرائع حقًا إذا كان يمكن القيام بذلك تلقائيًا. خاصة بسبب تعامل Discourse مع الصور بطريقة ذكية، مع منع إنشاء ملفات مكررة إذا استخدمت العديد من المنشورات نفس الصورة. الجانب الآخر هو أنه من الممل جدًا إزالة الصور الفردية التي تم استخدامها كثيرًا.
لقد تعرضت لشخص ما لبريد محتوى احتيالي عبر عدة حسابات قبل ذلك وكان الأمر مرهقًا للغاية في محاولة التعامل معه والتأكد من إزالته بالكامل (جميع الملفات الأصلية، الملفات المحسّنة، ذاكرة التخزين المؤقت لشبكة توصيل المحتوى، المنشورات، صور الأفاتار، شعارات المستخدم، إلخ).
لقد اقترحت هذه الميزة، لأنها ستكون مفيدة جدًا في رأيي. إذا تم تنفيذ ذلك، بالإضافة إلى التنقية التلقائية للمحتوى الموجود في المنشورات المحذوفة، أعتقد أنه سيتم تغطية جميع الحالات ويمكن التعامل معها دون الوصول إلى SSH.