Re-adding missing uploads to the database

حسنًا، لقد قمت بحلها باستخدام كلود والكثير من الثناء. أشارك ما فعلته لمساعدة أي شخص آخر لديه مشكلة مماثلة أو متطابقة.

لست متأكدًا مما إذا كانت هذه هي الطريقة الأكثر ذكاءً والأمثل للاستخدام، بل هي الطريقة التي نجحت معي.

يرجى توخي الحذر وتذكر أنني لست خبيرًا بل مبتدئ يتعلم دائمًا.

المشكلة (من S3 إلى نظام الملفات المحلي)

بعد الترحيل من AWS S3 إلى نظام الملفات المحلي، ظهرت العديد من الصور كـ transparent.png. كانت الملفات موجودة دائمًا على القرص ولكن Discourse لم يتمكن من استردادها.

كان السبب الجذري عبارة عن سلسلة مكسورة:

  1. المنشورات ذات عناوين URL القصيرة upload:// (تشفير Base62 لـ SHA1).
  2. قاعدة البيانات uploads تربط SHA1 بمسار ملف محلي.
  3. نظام الملفات يخزن الملفات المسماة بواسطة تجزئة 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 عن طريق الخطأ سابقًا وأدى إلى تشغيل عمليات الاستدعاء التي نقلت الملفات إلى سجل الحذف المؤقت.

استعدت ملفًا فرديًا استخدمته للاختبار وأعدت صياغة طريقتي.

3 إعجابات