فشل النسخ الاحتياطي إلى Cloudflare R2 أثناء التحميل متعدد الأجزاء باستخدام aws-sdk-s3 1.182.0 (طريقة 'downcase' غير معرفة لـ nil)

الأولوية/الشدة:

عالية للنسخ المستضافة ذاتيًا التي تستخدم تخزين نسخ احتياطية متوافق مع S3، حيث تفشل النسخ الاحتياطية المجدولة بعد إنشاء الأرشيف.

المنصة:

Discourse مستضاف ذاتيًا على أحدث فرع.

الإصدار الحالي المباشر عند الملاحظة: v2026.4.0-latest

Ruby: 3.4.0

aws-sdk-s3: 1.182.0

الوصف:

تفشل النسخ الاحتياطية إلى Cloudflare R2 في الخطوة النهائية “جاري تحميل الأرشيف…”.

يتم إكمال عملية تصدير قاعدة البيانات وإنشاء الأرشيف المحلي بنجاح، لكن عملية التحميل متعدد الأجزاء للأرشيف النهائي تفشل.

النتيجة الفعلية:

يفشل النسخ الاحتياطي مع الرسالة:

EXCEPTION: multipart upload failed: undefined method 'downcase' for nil

يتضمن تتبع المكدس:

aws-sdk-s3-1.182.0/lib/aws-sdk-s3/multipart_file_uploader.rb
lib/backup_restore/s3_backup_store.rb:48
lib/backup_restore/creator.rb:434

النتيجة المتوقعة:

يجب أن يتم تحميل أرشيف النسخ الاحتياطي بنجاح إلى مخزن النسخ الاحتياطي المتوافق مع S3 المُهيأ.

خطوات التكرار:

  1. قم بتكوين تخزين النسخ الاحتياطي لـ Cloudflare R2 باستخدام مسار النسخ الاحتياطي المتوافق مع S3.
  2. استخدم أرشيف نسخ احتياطي أكبر من عتبة التحميل متعدد الأجزاء.
  3. قم بتشغيل نسخة احتياطية يدوية أو مجدولة.
  4. راقب الفشل أثناء “جاري تحميل الأرشيف…”.

الإعدادات ذات الصلة:

  • DISCOURSE_BACKUP_LOCATION=s3
  • DISCOURSE_S3_ENDPOINT=https://.r2.cloudflarestorage.com
  • DISCOURSE_S3_FORCE_PATH_STYLE=true
  • DISCOURSE_S3_BACKUP_BUCKET=
  • AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED
  • AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED

مقتطف من تتبع المكدس الملاحظ:

algorithm = resp.context.params[:checksum_algorithm]
k = "checksum_#{algorithm.downcase}".to_sym

هذا يشير إلى أن checksum_algorithm هو nil في مسار التحميل متعدد الأجزاء.

سياق إضافي:

هناك موضوع حديث مشابه على Meta للنسخ الاحتياطية إلى Backblaze B2:

أيضًا، تبدو مدخلات سجل التغييرات لـ aws-sdk-s3 بعد الإصدار 1.182.0 ذات صلة:

  • 1.201.0: إصلاح التحميل متعدد الأجزاء لاحترام وضع request_checksum_calculation عند when_required
  • 1.210.2: العودة إلى استخدام تجزئات الطلب عبر الرؤوس عند استخدام نقاط نهاية مخصصة أو موفري نقاط نهاية لعمليات PutObject و UploadPart

يبدو أن Discourse main لا يزال يقيد aws-sdk-s3 حاليًا على الإصدار 1.182.0:

https://raw.githubusercontent.com/discourse/discourse/main/Gemfile.lock