Пересборка старых постов не подтянет новый URL S3 CDN после переименования S3-бакета

После установки Discourse (2.7.0.beta1) и импорта старых постов из Google Groups я добавил конфигурацию ключа и ведра S3 (но без URL CDN) и выполнил команду:

rake uploads:migrate_to_s3

которая, казалось, работала отлично. Все изображения были загружены в S3, и Discourse пытался получить к ним доступ через автоматически сгенерированный URL S3 — что-то вроде:

https://ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/75747ca17a3ca01f298f836691e1990916bafccb.png

Затем я переименовал ведро (в ortus-discourse-uploads) и настроил дистрибуцию Cloudfront перед ним с CNAME, сконфигурированным через Cloudflare:

https://communitycdn.ortussolutions.com/

CNAME, Cloudfront и S3 работают отлично. URL-адреса вроде этого корректно отображают одно из изображений в ведре:

https://communitycdn.ortussolutions.com/original/1X/75747ca17a3ca01f298f836691e1990916bafccb.png

Однако проблема в том, что Discourse полностью застрял на старом домене ortus-discourse.s3.dualstack.us-west-2.amazonaws.com (который не работает из-за переименования ведра), и сколько бы раз я ни пересобирал контейнер или не перепаковывал старые посты, я никак не могу заставить Discourse использовать новый URL CDN. Я искал в Google целый день, перепаковал, наверное, с десяток раз (внутри контейнера app) с различными настройками. На каждом форуме дают один и тот же совет — пересобрать и перепаковать, но это не работает.

Поломаны не только изображения в постах: даже тег <link rel="icon" type="image/png" href=""> и логотип сайта застряли на старом домене и не используют URL CDN S3.

Вот мои текущие настройки S3:

  DISCOURSE_S3_ACCESS_KEY_ID: '********'
  DISCOURSE_S3_SECRET_ACCESS_KEY: '******'
  DISCOURSE_BACKUP_LOCATION: 's3'
  DISCOURSE_ENABLE_S3_UPLOADS: true
  DISCOURSE_S3_BUCKET: 'ortus-discourse-uploads'
  DISCOURSE_S3_UPLOAD_BUCKET: 'ortus-discourse-uploads'
  DISCOURSE_S3_BACKUP_BUCKET: 'ortus-discourse-backups'
  DISCOURSE_S3_REGION: 'us-west-2'
  DISCOURSE_S3_CDN_URL: https://communitycdn.ortussolutions.com

  DISCOURSE_CDN_URL: https://community.ortussolutions.com

Я даже пробовал перемапить старый URL на новый в постах так:

rake posts:remap["ortus-discourse.s3.dualstack.us-west-2.amazonaws.com","communitycdn.ortussolutions.com"]

но команда сообщила, что ни один пост не был затронут.

Ни в одной из переменных окружения или настроек базы данных у меня нет ссылок на старое имя ведра ortus-discourse, поэтому я не могу понять, откуда Discourse продолжает брать это имя. Я новичок в Discourse и не разработчик на Ruby, поэтому не копался глубже того, что вижу в файле app.yml, в административном интерфейсе и в выводе команд rake, которые нашел на форумах.

Какова ценность этих загрузок в таблице Uploads?

./launcher enter app
rails c
Upload.all.sample(10).pluck(:url)

@Falco Спасибо за ответ. Вот вывод этой команды.

root@discourse-app:/var/www/discourse# rails c
Upload.all.sample(10).pluck(:url)
[1] pry(main)> Upload.all.sample(10).pluck(:url)
=> ["//ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/52b3aff4e63a7e38bef42d469bafd1ed7c1cc1a2.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/9f90374a280a4681332bcd2191b8de43462f8776.png",
 "//ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/29691fba566fc998a966aa93859753e3cf0b8528.cfc",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/6ae912ced40d60adc1356c1d7acf144b0fa0985a.jpeg",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/4dfe5b48fc8cb5d79880d70355c34d7ed02be812.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/897c4b4e755c1c8e93224a27187dc631a02e4388.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/59886f322e6834b567d473138108fab6e0f33764.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/e3e3429d63155cf0d850e161846d187bc6f273ea.jpeg",
 "//ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/1b701869b4b235daa8d6a9a7728766f3b4e69814.txt",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/c83aaee941462d47ef91f0c6448257d07487b231.png"]
[2] pry(main)>

Итак, действительно, есть несколько файлов с старым бакетом.

Вам нужна следующая перенастройка:

./launcher enter app
rails c
DbHelper.remap("ortus-discourse.s3.dualstack.us-west-2.amazonaws.com", "ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com")

Пожалуйста, сначала сделайте резервную копию, так как отменить эту операцию нельзя.

@Falco Спасибо ещё раз. Я выполнил два перенаправления:

DbHelper.remap("ortus-discourse.s3.dualstack.us-west-2.amazonaws.com", "communitycdn.ortussolutions.com")
DbHelper.remap("ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com", "communitycdn.ortussolutions.com")

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


Пока мы ждём завершения пересборки, что пошло не так? Это баг в Discourse, из-за которого мои загрузки застряли на старом URL и не переключились на новый?

Я читал подобные посты, например этот, где говорилось о смене URL CDN, но в них упоминалось только о замене строк в сообщениях (что не сработало), и ничего не говорилось о перенаправлении через DbUtil.

Я даже пытался снова запустить скрипт импорта в S3 через rake, но получил ошибку (извините, я не записал её в тот момент).

Также я нашёл скрипт migrate_from_s3 для rake, который почти запустил, чтобы попробовать начать с нуля, но затем обнаружил пост на форуме, где указывалось, что его запуск испортит базу данных, поэтому я оставил его в покое.

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

К сожалению, повторная пересборка, похоже, не исправила изображения, встроенные в сообщения. Что интересно: если я открою старое сообщение и отредактирую его, то увижу, что изображение представлено примерно так:

![COMMANDBOXERROR.png|1169x984](upload://yTDVQSa4wbIeLGEZvE7muXe8sAJ.png)

но при просмотре сообщения в нём просто большое пустое пространство, указывающее на

https://community.ortussolutions.com/images/transparent.png

Это относительно недавнее изменение. Ещё вчера большинство таких изображений указывало на старый неверный URL S3, но где-то вчера вечером или сегодня появился этот прозрачный PNG.

Хм, это не то, что я советовал вам сделать в моём ответе :face_with_raised_eyebrow:

В таблице uploads мы ожидаем указание пути к S3, и замена на CDN происходит только в процессе обработки (cook) markdown-разметки.

Вы указали CDN в таблице Uploads, что не соответствует обычной работе программного обеспечения.

Извини, я предположил, что ты просто недостаточно внимательно прочитал первое сообщение (OP) и не заметил, что я упомянул распределение Cloudflare, и что мне нужно было немного его настроить под свой реальный URL. Я не осознавал, что нежелательный URL где-то хранится в базе данных. Я почти написал и спросил, так ли это, но казалось, что очевидно, что мне нужно сделать.

Ничего страшного, я могу легко перенастроить эти ссылки обратно на URL S3. Это новая установка Discourse, и весь загруженный контент находится в одном месте, так что переключить несложно.

Мои вопросы о том, что пошло не так в моём предыдущем сообщении, всё ещё актуальны.

Я считаю, что всё просто: мы не поддерживаем смену бакета Object Storage.

Под «поддержкой» здесь подразумевается, что вы не можете изменить бакет и рассчитывать на корректную работу. Также нет ни письменного руководства, ни заранее подготовленной задачи rake для этого. Поэтому, если вам всё же потребуется сменить бакет, придётся выполнить некоторые манипуляции с базой данных.

Хорошо, справедливо. Таким образом, моей главной ошибкой было переименование бакета S3 и предположение, что обновление имени бакета в админ-панели решит все проблемы. Возможно, здесь было бы полезно добавить предупреждение в интерфейсе администратора при изменении имени бакета. (Сначала я настраивал параметры через админ-панель, прежде чем переключился на использование переменных окружения, думая, что это как-то поможет.) Определённо не было ясно, что изменение имени бакета после загрузки может вызвать проблемы.

Я вернул маппинг доменов обратно на правильный домен AWS S3.

DbHelper.remap("communitycdn.ortussolutions.com", "ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com")
[1] pry(main)> Upload.all.sample(10).pluck(:url)
=> ["//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/fc05f9be9b783479819fec68b1d8e493110007a4.cfc",
 "/images/d-logo-sketch-small.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/50f0d6f260cdb4ef91e29023d92b46df096ab34e.cfc",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/65d80cddc6dc15b9a4d1b9e9d88cc9a8928c5316.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/a86aa2a12183428f3289caa95787ea16f22e2e4d.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/9f76b5238b147a60c8ad5f65bd7fa4bb6b58d852.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/6a4c9b992e6cd8a15ddeaec0d158ebd473164525.zip",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/3a532dec6390d5087ed6154fc0335c2c0f1ea543.zip",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/93420848249ecea2261d405e46f7f450cc02a3af.txt",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/d67c39e06ce624b9deb7625dd041d21cffd96df9.png"]

Я снова пересобрал приложение и теперь пересобираю посты. Посмотрим, с 37-й попытки повезёт :slight_smile:

Все загрузки имеют правильный URL ведра S3, контейнер пересобран, и все 30 тысяч постов пересозданы. Однако я всё ещё вижу

/images/transparent.png

вместо всех своих изображений.

При редактировании постов это отображается так:

![COMMANDBOXERROR.png|1169x984](upload://yTDVQSa4wbIeLGEZvE7muXe8sAJ.png)

Что интересно, другие вложения, например zip-файлы, теперь работают корректно.

Не хватает ли какого-то элемента для того, чтобы встроенные изображения в старых постах начали работать?

Можете вывести атрибуты объекта Upload, соответствующего yTDVQSa4wbIeLGEZvE7muXe8sAJ?

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

[17] pry(main)> Upload.all.sample(1)
=> [#<Upload:0x00005633230f8af0
  id: 353,
  user_id: 273,
  original_filename: "helloWorldF.zip",
  filesize: 50542,
  width: nil,
  height: nil,
  url: "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/3a532dec6390d5087ed6154fc0335c2c0f1ea543.zip",
  created_at: Wed, 30 Dec 2020 18:46:31 UTC +00:00,
  updated_at: Wed, 30 Dec 2020 18:46:31 UTC +00:00,
  sha1: "3a532dec6390d5087ed6154fc0335c2c0f1ea543",
  origin: nil,
  retain_hours: nil,
  extension: "zip",
  thumbnail_width: nil,
  thumbnail_height: nil,
  etag: nil,
  secure: false,
  access_control_post_id: nil,
  original_sha1: nil,
  animated: nil,
  verification_status: 1>]

Также я нашёл ссылки на документацию по ActiveRecord в Ruby on Rails для поиска конкретных записей, но не смог найти там никаких данных, которые хоть отдалённо напоминали бы yTDVQSa4wbIeLGEZvE7muXe8sAJ. Как мне найти соответствующую запись загрузки?

О, отличная новость. Пока я изучал, как найти записи о загрузках, я наткнулся на этот пост, который показал, как преобразовать строку base62 в хеш sha1.

В нём упоминалось, что изображения, отображающие только transparent.png, были «похоронены» (tombstoned). Я не до конца понимаю, что это значит, но предполагаю, что какой-то процесс запустился ночью, когда изображения были повреждены, и пометил их как неиспользуемые. Мне удалось выполнить:

rake uploads:recover_from_tombstone

и, похоже, все мои встроенные изображения вернулись и теперь указывают на мой S3 CDN!

Кстати, вот как я нашёл запись о загрузке, начиная со строки yTDVQSa4wbIeLGEZvE7muXe8sAJ.

[14] pry(main)> Base62.decode("yTDVQSa4wbIeLGEZvE7muXe8sAJ").to_s(16)
=> "f49428d6af35d7e0414408ccb65e7316f5003215"
[15] pry(main)> Upload.where( "original_filename ilike '%f49428d6af35d7e0414408ccb65e7316f5003215%'" )
=> [#<Upload:0x000056313aa91fe8
  id: 899,
  user_id: 549,
  original_filename: "f49428d6af35d7e0414408ccb65e7316f5003215.png",
  filesize: 25514,
  width: 1169,
  height: 984,
  url: "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/f49428d6af35d7e0414408ccb65e7316f5003215.png",
  created_at: Tue, 12 Jan 2021 23:01:35 UTC +00:00,
  updated_at: Tue, 12 Jan 2021 23:01:36 UTC +00:00,
  sha1: "f49428d6af35d7e0414408ccb65e7316f5003215",
  origin: nil,
  retain_hours: nil,
  extension: "png",
  thumbnail_width: 594,
  thumbnail_height: 500,
  etag: "6977f35ddbf39a4399dc76f92a5079d4",
  secure: false,
  access_control_post_id: nil,
  original_sha1: nil,
  animated: nil,
  verification_status: 1>]

Ещё раз спасибо за вашу помощь, @Falco! Я новичок в Discourse, но вы оказались очень терпеливым и отзывчивым :+1: