Ссылки на битые загрузки в темах вызывают ошибки 500 в версии 2.5.0

Я администрирую сайт на Discourse и хочу начать с того, как сильно я люблю этот программный продукт. Спасибо всей команде за отличную работу — это потрясающий инструмент.

После обновления до версии 2.5.0 у меня возникли серьёзные проблемы. Вот краткое изложение ситуации и моё временное решение. Возможно, это поможет разработчикам найти более надёжное исправление в будущих версиях.

Некоторые темы в нашей базе данных содержат битые загрузки. Мы использовали функцию «Загрузки в S3» и по ошибке удалили бакет. Да, это очень глупый поступок, но мы его совершили! В результате все изображения в темах были утеряны.

За исключением потери множества изображений, всё работало нормально: Discourse показывал битые ссылки на несуществующие картинки, но в остальном проблем не было.

Однако при попытке обновиться до версии 2.5.0 всё пошло не так: у всех авторизованных пользователей возникали ошибки 500, в то время как анонимные посетители могли просматривать сайт.

После расследования я понял, что Discourse падает из-за ошибок «Файл не найден». Похоже, он пытался их загрузить. Мне пришлось принудительно установить метод local? в значение true в файле /var/www/discourse/app/models/upload.rb, и это помогло. Но я немного беспокоюсь насчёт следующих обновлений…

Это явно что-то новое, так как предыдущие обновления не вызывали таких проблем.

Кстати, есть ли какой-то способ, следуя которому, можно удалить все неработающие ссылки на изображения в наших темах?

Спасибо.

У нас наблюдается обратное поведение: авторизованный пользователь работает нормально, а неавторизованные не могут подключиться и получают ошибку 500.

Можете предоставить полный стек вызовов (backtrace) такой ошибки?
Проверьте страницу /logs.

Мне это очень похоже на несовместимый плагин. Какие неофициальные плагины вы используете? Пробовали ли вы пересобрать систему без них?

Конечно, в моём файле log/production.log было следующее исключение (когда Discourse обращался к пустому бакету S3, который я воссоздал в надежде, что это решит проблему).

Started GET “/” for 86.246.127.170 at 2020-05-16 14:29:06 +0000
Processing by ListController#latest as HTML
Creating scope :open. Overwriting existing method Poll.open.
Completed 500 Internal Server Error in 3638ms (ActiveRecord: 0.0ms | Allocations: 135090)
NoMethodError (undefined method path' for nil:NilClass) /var/www/discourse/lib/file_store/base_store.rb:150:in cache_file’

Надеюсь, это поможет.

Спасибо, возможно, дело в этом. У меня действительно установлены два плагина: Discourse Adsense и discourse-chat-integration. Я попробую пересобрать систему без них.

Я могу подтвердить, что это не вызвано плагином: я воспроизвел ту же ошибку при чистой установке + восстановлении моей последней резервной копии и без установленных плагинов, за исключением docker_manager.

Первый стектрейс, который я получил:

Завершено с ошибкой 500 Internal Server Error за 4169 мс (ActiveRecord: 0.0 мс | Выделения: 72058)
NoMethodError (не определен метод path для nil:NilClass)
/var/www/discourse/lib/file_store/base_store.rb:150:in `cache_file’

Я исправил это следующим образом:

def cache_file(file, filename)
path = get_cache_path_for(filename)
dir = File.dirname(path)
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)

  if file.nil?
    return
  end

  FileUtils.cp(file.path, path)

Это привело ко второй ошибке (той, о которой я упомянул в своем первоначальном посте):

Начат GET “/” для 86.246.127.170 в 2020-05-18 07:37:40 +0000
Обработка запроса CategoriesController#index как HTML
Завершено с ошибкой 500 Internal Server Error за 4342 мс (ActiveRecord: 0.0 мс | Выделения: 60478)
NoMethodError (не определен метод path для nil:NilClass)
/var/www/discourse/app/models/upload.rb:193:in `fix_dimensions!’

Что я исправил, принудительно установив local? в true:

def local?
return true
!(url =~ /^(https?:)?///)
end

Перемещали ли вы когда-либо свои файлы в S3 или из S3?

Да, я сделал. Но затем бакет был удалён. И я вернулся к локальному хранилищу (с неработающими ссылками на изображения в предыдущих темах, разумеется).

Я думаю, лучший вариант здесь — полностью удалить все некорректные строки Upload из вашей базы данных.

Если загрузка отсутствует, не храните её там.

Да, я согласен, но боюсь запускать такой «ядерный» скрипт вручную на базе данных. Есть какие-нибудь предложения, как сделать это «правильно»? Или всё-таки нужно делать это вручную?

Кроме того, у меня складывается ощущение, что это изменение поведения в Discourse немного тревожно. Насколько я понимаю, если где-то появится битая ссылка на изображение, приложение может упасть.

Раньше такого не было. Я бы предложил сделать систему более устойчивой в подобных ситуациях.

Очень похоже на то, что у нас:

«Исправил» это, запустив заново мастер настройки!

Да, похоже, это та же проблема. @sukria, если вы обновитесь до последней версии с успешным прохождением тестов, я добавил исправление, которое делает обработку повреждённых загрузок более надёжной (хотя вам всё же стоит попытаться очистить ссылки на повреждённые загрузки).

Мне также интересно найти простой способ исправить эти битые ссылки :wink:

Спасибо @david, подтверждаю, что чистая сборка на основе tests-passed заработала сразу. Спасибо!
Есть ли какие-либо предложения по правильному/простому способу избавиться от нерабочих ссылок в темах?