فشل تحميل النسخة الاحتياطية بسبب عدم تهيئة TransferManager

بعد التحديث إلى v2026.8.0-latest.1 +4، بدأت عمليات النسخ الاحتياطي تفشل. هذه هي السجلات: log.txt.zip (22.1 كيلوبايت)

على وجه الخصوص، إليك القسم الذي يبدو ذا صلة:

[2026-08-04 03:37:52] جاري رفع الأرشيف...
[2026-08-04 03:37:52] EXCEPTION: ثابت غير مهيأ Aws::S3::TransferManager
[2026-08-04 03:37:52] /var/www/discourse/lib/s3_helper.rb:453:in 'S3Helper#transfer_manager'
/var/www/discourse/lib/s3_helper.rb:332:in 'S3Helper#upload_file'
/var/www/discourse/lib/backup_restore/s3_backup_store.rb:48:in 'BackupRestore::S3BackupStore#upload_file'
/var/www/discourse/lib/backup_restore/creator.rb:437:in 'BackupRestore::Creator#upload_archive'
/var/www/discourse/lib/backup_restore/creator.rb:41:in 'BackupRestore::Creator#run'
/var/www/discourse/lib/backup_restore.rb:13:in 'BackupRestore.backup!'
/var/www/discourse/app/jobs/regular/create_backup.rb:10:in 'Jobs::CreateBackup#execute'
/var/www/discourse/app/jobs/base.rb:313:in 'block (2 levels) in Jobs::Base#perform'

أنا غير متأكد من كيفية حل هذه المشكلة.

حدّثت إلى v2026.9.0-latest +565، لكنني ما زلت أواجه نفس المشكلة تمامًا.

الإصدار الذي تعمل عليه من Discourse يتضمن إصدارًا من aws-sdk-s3 يجب أن يوفر Aws::S3::TransferManager.

هل تستخدم تثبيت Docker الرسمي لـ Discourse؟ إذا كنت تستخدم إعداد Docker الرسمي، هل تم إعادة بناء الحاوية بالكامل كجزء من عملية الترقية؟

نعم، أعتقد أنني أستخدم تثبيت Docker الرسمي لـ Discourse. هل هناك طريقة للتأكد من ذلك؟ لقد مرّ وقت طويل منذ أن قمت بالتثبيت.

للتحديث، قمت بتشغيل ./launcher rebuild app. أفترض أن هذا يعني أن الحاوية (container) أُعيد بناؤها بالكامل، لكن ربما أكون مخطئًا؟

بعض التفاصيل الإضافية التي قد تكون ذات صلة:

  • يعمل النظام على Ubuntu 24.04.4 LTS
  • يقوم ملف app.yml بتثبيت الإضافات الرسمية docker_manager وdiscourse-doc-categories داخل خطاف after_code. لا توجد أي إضافات أخرى معرّفة في app.yml.
  • أحاول تخزين النسخ الاحتياطية في تخزين متوافق مع S3 توفّره Backblaze، وكان هذا يعمل من قبل.

قد يساعد في تحديد المشكلة التحقق من أي إصدار من مكتبة aws-sdk-s3 يتم تحميله فعليًا داخل الحاوية قيد التشغيل.

التغيير في Discourse الذي أدخل Aws::S3::TransferManager قام أيضًا بترقية aws-sdk-s3 من 1.182.0 إلى 1.227.0:

في إصدار Discourse الذي أشرت إليه، يجب أن يكون ملف Gemfile.lock لا يزال يستخدم aws-sdk-s3 الإصدار 1.227.0، والذي يوفر Aws::S3::TransferManager.

هل يمكنك محاولة الدخول إلى الحاوية:

cd /var/discourse
./launcher enter app

ثم، داخل الحاوية:

cd /var/www/discourse
bundle info aws-sdk-s3
bundle exec ruby -e '
require "aws-sdk-s3"
puts "gem: #{Gem.loaded_specs["aws-sdk-s3"]&.full_name}"
puts "path: #{Gem.loaded_specs["aws-sdk-s3"]&.full_gem_path}"
p Aws::S3.autoload?(:TransferManager)
p Aws::S3::TransferManager
'

قد يكون من المفيد أيضًا التحقق من التطبيق نفسه تحت بيئة Rails:

RAILS_ENV=production bundle exec rails runner '
puts "aws-sdk-s3: #{Gem.loaded_specs["aws-sdk-s3"]&.version}"
p Aws::S3.autoload?(:TransferManager)
p Aws::S3::TransferManager
'

ثم اترك الحاوية باستخدام الأمر:

logout

إذا أفاد الأمر بإصدار أقدم من aws-sdk-s3، أو إذا كان TransferManager مفقودًا،
فسيفسر ذلك استثناء النسخ الاحتياطي، وسيشير إلى أن المكتبات المثبتة في الحاوية لا تتطابق مع ملف
Gemfile.lock الحالي لـ Discourse.

إذا أفاد الأمر بالإصدار 1.227.0 ونجح في حل
Aws::S3::TransferManager، فإن المشكلة تكون أكثر غرابة، وسنعرف أن علينا النظر فيما يختلف بين عملية النسخ الاحتياطي في Sidekiq وتلك البيئة التفاعلية.

بما أنك تستخدم ./launcher rebuild app، يبدو ذلك أنه يتبع سير عمل discourse_docker القياسي؛ الأوامر المذكورة أعلاه ستخبرنا بدقة أكبر بما انتهى به الحال في الحاوية المُعاد بناؤها.

يبدو أن لديّ إصدارًا قديمًا من aws-sdk-s3.

$ bundle info aws-sdk-s3
  * aws-sdk-s3 (1.177.0)
	Summary: AWS SDK for Ruby - Amazon S3
	Homepage: https://github.com/aws/aws-sdk-ruby
	Source Code: https://github.com/aws/aws-sdk-ruby/tree/version-3/gems/aws-sdk-s3
	Changelog: https://github.com/aws/aws-sdk-ruby/tree/version-3/gems/aws-sdk-s3/CHANGELOG.md
	Path: /var/www/discourse/vendor/bundle/ruby/3.4.0/gems/aws-sdk-s3-1.177.0

أثناء البحث في هذه المسألة، تذكّرت أنني استخدمت هذا الحل البديل للالتفاف على مشكلة عدم عمل AWS SDK مع Backblaze. بعد الاطلاع على آخر مستجدات الموضوع، يبدو أن Backblaze حدّثت واجهة برمجية (API)، مما يجعل الحل البديل غير ضروري.

بعد إزالة الحل البديل، نجحت عملية النسخ الاحتياطي! شكرًا على المساعدة. :heart:

فكرة واحدة من هذا: قد تكون قوالب التوافق المؤقتة مثل هذه أكثر أمانًا إذا كانت تحتوي على نوع من الشروط الذاتية الانتهاء أو الحماية، بدلاً من الاستمرار في تجاوز تبعيات Discourse بشكل غير محدود.

على سبيل المثال، مع عمليات الاستيراد المؤقتة للمصدر، أخطط لاستخدام الخطافات (hooks) في بيئة الإنتاج التي تتحقق أولاً مما إذا كان الإصلاح الموجود في المصدر الأصلي (upstream) موجودًا بالفعل، وتطبق الرقعة (patch) فقط إذا كانت لا تزال مطلوبة.

في هذه الحالة، كان من الممكن أن يمنع شيء على هذا الخط استمرار تثبيت aws-sdk-s3 1.177.0 القديم بمجرد أن بدأ Discourse نفسه في الاعتماد على وظائف SDK الأحدث:

hooks:
  after_bundle_exec:
    - exec:
        cd: $home
        cmd:
          - |
            if grep -q "Aws::S3::TransferManager" lib/s3_helper.rb; then
              echo "Discourse now requires Aws::S3::TransferManager; skipping obsolete Backblaze aws-sdk-s3 downgrade"
            else
              echo "Applying temporary Backblaze aws-sdk-s3 compatibility pin"
              bundle config set frozen false
              sed -i 's/gem "aws-sdk-s3", require: false/gem "aws-sdk-s3", "1.177.0", require: false/' Gemfile
              bundle update aws-sdk-s3
              bundle add aws-sdk-core --version 3.215
            fi

إن تلك الفحصية المحددة مجرد مثال توضيحي - من المرجح أن يكون فحص إصدارات أكثر عمومية أو فشلًا صريحًا عند تجاوز Discourse للإصدار المتوقع من SDK أفضل.

حتى الفشل بصوت عالٍ سيكون على الأرجح تفضيليًا على إنتاج حاوية بصمت حيث لم تعد جوهاتها (gems) تطابق الإصدارات التي يتوقعها Discourse.

أوافق على أنه كان من الجيد أن يفشل النظام بصوت عالٍ، لكن الأمر كان كذلك من قبل لأنني أردت ألا تتطابق الجواهر (gems) مع الإصدارات التي يتوقعها Discourse، لأن الإصدار الأحدث من aws-sdk-s3 كان يرسل ترويسات (headers) لا تدعمها Backblaze، وكنت أريد أن تعمل النسخ الاحتياطية.

لا أعلم ما إذا كان هناك فحص يمكنني ضبطه بشكل استباقي مسبقًا لإشعاري عندما لم يعد الحل البديل ضروريًا. لقد طبّقت الحل البديل قبل عام ونصف، في أبريل 2025، قبل أن يصبح الإصلاح متاحًا.

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