Версия Discourse, которую вы используете, включает версию aws-sdk-s3, которая должна предоставлять Aws::S3::TransferManager.
Вы используете официальную установку Discourse в Docker? Если вы используете официальный Docker-набор, был ли контейнер полностью пересобран в рамках обновления?
Да, я полагаю, что использую официальную установку Discourse через Docker. Есть ли способ убедиться в этом наверняка? Прошло довольно много времени с момента установки.
Для обновления я выполнил ./launcher rebuild app. Я предполагаю, что это означает полную пересборку контейнера, но, возможно, я ошибаюсь?
Ещё несколько деталей, которые могут быть важны:
Используется Ubuntu 24.04.4 LTS
В app.yml в хуке after_code устанавливаются официальные плагины docker_manager и discourse-doc-categories. Другие плагины в app.yml не определены.
Я пытаюсь хранить резервные копии в S3-совместимом хранилище, предоставляемом Backblaze, и ранее это работало.
Чтобы сузить область поиска, можно проверить, какой именно gem 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, это объяснит исключение при резервном копировании и укажет на то, что установленные в контейнере gems не соответствуют текущему Gemfile.lock Discourse.
Если же будет указана версия 1.227.0 и Aws::S3::TransferManager успешно резолвится, то проблема более необычна, и нам нужно будет посмотреть, чем отличается процесс резервного копирования Sidekiq от этой интерактивной среды.
Поскольку вы используете ./launcher rebuild app, это действительно похоже на стандартный рабочий процесс discourse_docker; приведенные выше команды помогут нам более точно понять, что именно оказалось в пересобранном контейнере.
Изучение этого вопроса напомнило мне, что я использовал это обходное решение, чтобы обойти проблему с тем, что AWS SDK не работает с Backblaze. Ознакомившись с обсуждением, я выяснил, что Backblaze обновила свой API, из-за чего обходное решение стало ненужным.
После того как я удалил обходное решение, резервное копирование успешно завершилось! Спасибо за помощь.
Одна мысль по этому поводу: временные шаблоны совместимости, подобные этому, могут быть безопаснее, если они имеют某种 механизм самовыключения или условия защиты, а не продолжают бесконечно переопределять зависимости Discourse.
Например, для временных бэкпортов исходного кода я планирую использовать хуки в production, которые сначала проверяют, присутствует ли уже исправление в upstream, и применяют патч только в том случае, если он всё ещё необходим.
В данном случае, что-то вроде следующего могло бы потенциально предотвратить продолжение использования закреплённой версии 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 теперь требует Aws::S3::TransferManager; пропускаем устаревшее понижение версии aws-sdk-s3 Backblaze"
else
echo "Применяем временный pin совместимости aws-sdk-s3 Backblaze"
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.
Хотя я согласен, что было бы хорошо, если бы ошибка сообщалась явно, до этого момента я хотел, чтобы версии гемов не совпадали с версиями, ожидаемыми Discourse, поскольку более новая версия aws-sdk-s3 отправляла заголовки, которые Backblaze не поддерживал, и я хотел, чтобы резервное копирование работало.
Я не знаю, была ли какая-то проверка, которую я мог бы настроить заранее, чтобы получать уведомления, когда обходное решение больше не потребуется. Я внедрил обходное решение год и полтора назад, в апреле 2025 года, до того, как стала доступна исправление.
Думаю, лучшее, что я мог бы сделать, — это добавить срок действия, чтобы заставить себя проверять, нужно ли всё ещё обходное решение. Подобная функциональность могла бы быть полезной. Или, может быть, на мне лежит ответственность быть более проактивным и устанавливать напоминания для проверки того, нужно ли всё ещё обходное решение. В этом отношении мне помогли некоторые заметки.