حسنًا، لقد قمت بحلها باستخدام كلود والكثير من الثناء. أشارك ما فعلته لمساعدة أي شخص آخر لديه مشكلة مماثلة أو متطابقة.
لست متأكدًا مما إذا كانت هذه هي الطريقة الأكثر ذكاءً والأمثل للاستخدام، بل هي الطريقة التي نجحت معي.
يرجى توخي الحذر وتذكر أنني لست خبيرًا بل مبتدئ يتعلم دائمًا.
المشكلة (من S3 إلى نظام الملفات المحلي)
بعد الترحيل من AWS S3 إلى نظام الملفات المحلي، ظهرت العديد من الصور كـ transparent.png. كانت الملفات موجودة دائمًا على القرص ولكن Discourse لم يتمكن من استردادها.
كان السبب الجذري عبارة عن سلسلة مكسورة:
- المنشورات ذات عناوين URL القصيرة
upload://(تشفير Base62 لـ SHA1). - قاعدة البيانات
uploadsتربط SHA1 بمسار ملف محلي. - نظام الملفات يخزن الملفات المسماة بواسطة تجزئة SHA1 الخاصة بها،
نقل الترحيل الملفات إلى القرص بشكل صحيح، ولكن لم تكن هناك سجلات قاعدة بيانات uploads موجودة. بدون سجل مطابق، يعود Discourse إلى transparent.png.
الحل (إنشاء السجلات وإعادة الخَبز)
إنشاء سجلات التحميل المفقودة من الملفات اليتيمة:
dir = Rails.root.join("public", "uploads", "default", "original")
created = 0
Dir.glob(dir.join("**", "*")).select { |f| File.file?(f) }.each do |path|
sha = File.basename(path, File.extname(path))
next if Upload.find_by(sha1: sha)
ext = File.extname(path).delete(".")
relative = path.sub("#{Rails.root}/public", "")
u = Upload.new
u.sha1 = sha
u.url = relative
u.original_filename = File.basename(path)
u.filesize = File.size(path)
u.extension = ext
u.user_id = -1
u.save!(validate: false)
created += 1
puts "Created upload #{u.id}: #{sha}"
end
puts "Total created: #{created}"
إعادة خَبز المنشورات التي تشير إلى عمليات التحميل المستعادة:
fixed_posts = 0
Upload.where(user_id: -1).find_each do |u|
short = u.short_url
next unless short
Post.where("raw LIKE '%upload://%'").find_each do |p|
urls = p.raw.scan(/upload:\/\/\[^\s\]\)]+/)
urls.each do |url|
decoded = Upload.sha1_from_short_url(url)
if decoded == u.sha1
p.rebake!
fixed_posts += 1
puts "Rebaked post #{p.id}"
break
end
end
end
end
puts "Total rebaked: #{fixed_posts}"
إعادة إنشاء الملفات المحسّنة المفقودة:
بعد إصلاح الملفات الأصلية، نحتاج إلى ملء الملفات المحسّنة (1X، 2X، إلخ).
rake uploads:regenerate_missing_optimized
التراجع الآمن (فقط في حال)
تستخدم جميع السجلات التي تم إنشاؤها user_id: -1. للإلغاء:
Upload.where(user_id: -1).delete_all
delete_all يتخطى عمليات الاستدعاء (callbacks) لذلك تظل ملفات نظام الملفات سليمة.
تم استخدام
destroy_allعن طريق الخطأ سابقًا وأدى إلى تشغيل عمليات الاستدعاء التي نقلت الملفات إلى سجل الحذف المؤقت.استعدت ملفًا فرديًا استخدمته للاختبار وأعدت صياغة طريقتي.