Аватары пропали после восстановления. Как их вернуть?

Доброе утро, @ariznaf,

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

# du -sh uploads

Например, на наших установках я сделал следующее:

Оригинальная установка:

# du -sh uploads
2.5G uploads

Установка только с сокетом (до исправления проблемы):

# du -sh uploads
444K uploads

Это дало мне подсказку, необходимую для того, чтобы понять, что мне нужно вручную скопировать папку uploads; и, зная проблему, решение становится простым.

Если вы проверите все свои различные папки uploads с помощью команды du -sh uploads во всех общих каталогах, это даст ценную подсказку о том, что происходит.

Если они различаются, значит, вы знаете, что некоторые файлы загрузки отсутствуют, и вы можете исправить это вручную.

Если они все одинаковы (маловероятно), то проблема становится более интересной :slight_smile:

Я нашёл проблему (но не решение).
Проблема не в самом восстановлении, а в изменении имени сервера.

Позвольте объяснить, как я выполнял восстановление (на случай, если я что-то упустил).

Я загрузил свежую копию Discourse с GitHub.
Запустил процесс docker-setup.
Перед запуском приложения и началом восстановления я отредактировал файл app.yml, чтобы настроить доступ к сокету.
Также изменил имя хоста на b.domain.com (изначально было a.domain.com).

Настроил nginx reverse proxy с использованием SSL для перенаправления трафика 443 (https) на сокет Discourse.
Затем выполнил пересборку (launcher rebuild app) и перезапустил nginx (service nginx restart).
Зашёл на https://b.domain.com, чтобы выполнить первоначальную настройку Discourse.
Настроил восстановление из S3 и восстановил последнюю резервную копию базы данных и загрузок (без миниатюр).
После восстановления вас автоматически выкидывает из системы.
Я отредактировал app.yml, скопировав содержимое app.yml со старого сайта (чтобы получить ту же конфигурацию и плагины).
Изменил имя хоста на b.domain.com в app.yml.

Снова выполнил пересборку и перезапуск nginx.

ПРОБЛЕМА сохраняется: изображения профилей (миниатюры) всех пользователей, которые меняли свои аватары, заменяются на стандартное белое изображение профиля.
Также отсутствует наш логотип в верхнем левом углу.

@Stephen параметр force_https был включён (как и на исходном сервере, где не было проблем). Я пробовал включать и выключать его, но это не дало эффекта. Оставил его включённым, так как мы хотим, чтобы наш сайт был доступен через https (в любом случае в конфигурации nginx трафик http:80 перенаправляется на https:443).

@riking Я использовал sidekiq и запустил задачу avatarmissing, которая, казалось, успешно завершилась за несколько миллисекунд. На случай, если это длительный процесс, я ждал почти 24 часа, чтобы проверить, восстановятся ли изображения профилей.
Но сегодня проблема та же: нет изображений аватаров (для тех, кто загрузил изображение профиля) и нет логотипа.

После этого я попытался проверить, связана ли проблема с изменением имени, как предложил @Stephen.

Я изменил имя хоста в app.yml и nginx обратно на a.domain.com (исходное), выполнил пересборку и перезапустил nginx.
Я изменил локальный файл hosts, чтобы a.domain.com указывал на IP нового сервера, и выполнил ping, чтобы убедиться, что происходит обращение к новому IP.

И ВОТ ОНО: аватары и профиль появились.

Таким образом, проблема не в самом процессе восстановления, а в том, что где-то сохраняются полные пути URL, и система пытается получить доступ к ним с неверного места.
Это странно, так как исходный сервер работает (он должен был найти изображения даже по неверному пути — на исходном сервере, а не на новом).

В любом случае, проблема не в процессе восстановления или необходимости повторно загружать изображения из-за какой-либо коррупции данных.

Проблема заключается в изменении имени сервера.

Теперь вопрос: как перенести форум Discourse с одного домена/имени хоста на другой?

Я снова попытался изменить имя хоста на b.domain.com.

Безрезультатно.

Кажется, что при использовании старого имени всё работает (но теперь я подозреваю, что оно подгружает изображения и прочее со старого сервера, который всё ещё работает в сети: я получаю новые посты и уведомления о новых публикациях с старого сервера, даже если я изменил IP-адрес для a.domain.com в моём файле hosts).

Я следовал инструкциям в этой теме, чтобы изменить имя хоста:

Я думал, что перенастройка Discourse с a.domain.com на b.domain.com решит проблему.
Даже выполнил команду rake posts:rebake, но результат тот же.

Я потерял аватары и логотип, а также изображения, вставленные в посты.

Наконец, как предложил @neounix, я распаковал все загрузки заново, чтобы заменить их в директории shared/standalone/uploads/, но безрезультатно — результат тот же.

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

Все данные и сообщения с самого начала существования форума несколько месяцев назад?

Как я уже говорил, мне удалось перенести сервер на другой, остановив его, скопировав все данные на новый и перезапустив.

Однако служба поддержки сообщила, что правильный способ — использование стандартного резервного копирования и восстановление базы данных.

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

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

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

Следуя этой истории:

https://meta.discourse.org/t/postgresql-12-update/151236/193

Я попробовал метод «резервное копирование и восстановление на другом экземпляре Discourse», и теперь столкнулся с этой проблемой. Перепробовал все известные приёмы (задачу Sidekiq, пересборку…), есть ли какая-то «подсказка» о том, что может быть причиной? Просто чтобы я мог попробовать что-то выяснить.

(Одно скажу вам: со всем этим я перешёл от «ну, я кое-как понимаю» к степени PhD по PostgreSQL, PhD по Redis… :stuck_out_tongue: Мне осталось только разобраться с Ruby и локальными окружениями для разработки, и я смогу стать полезным для сообщества :stuck_out_tongue: )

Исчезли все аватары или только часть? Пользовательские аватары по сути являются Uploads. Работают ли другие загрузки как ожидается?

Перейдите в консоль Rails и проверьте запись неработающего аватара в базе данных. Правильны ли у них значения URL, filesize, width, height, extension?

User.find_by_username('Overgrow').user_avatar
User.find_by_username('Overgrow').uploaded_avatar

Также у них должны присутствовать оптимизированные версии. Проверить это можно так:

OptimizedImage.where(upload_id: upload_id).where(version: 2)

Прежде всего, большое спасибо за вашу помощь, @Overgrow.

Все аватары и эмодзи (а также изображения сайта, такие как заголовки и т. д.) были «там», но невидимы. Для элементов, не связанных с аватарами, они отображаются как битые, а для аватаров — серый плейсхолдер. Некоторым пользователям удалось просто загрузить новый файл, и их аватары теперь видны.

При первой попытке выполнить команду я получил:

FATAL:  the database system is in recovery mode

Так что… вот это :eyes: (у меня часто происходят «разрывы соединения», поэтому я предполагаю, что это связано с базой данных, возможно?)

Но после того, как я продолжил попытки, в конце концов получил:

User.find_by_username(‘Overgrow’).user_avatar

=> #<UserAvatar:0x000055702722d200
 id: 4,
 user_id: 3,
 custom_upload_id: 20504,
 gravatar_upload_id: 12240,
 last_gravatar_download_attempt: Thu, 21 May 2020 10:16:55 UTC +00:00,
 created_at: Sat, 30 May 2019 16:33:16 UTC +00:00,
 updated_at: Thu, 21 May 2020 10:16:55 UTC +00:00>

(Пытался загрузить новый файл сегодня, но это не сработало).

User.find_by_username(‘Overgrow’).uploaded_avatar

=> #<Upload:0x00005555cd911b58
 id: 20504,
 user_id: 3,
 original_filename: "16_2.png.jpg",
 filesize: 56220,
 width: 360,
 height: 360,
 url: "/uploads/default/original/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8.jpeg",
 created_at: Thu, 15 Aug 2019 20:02:47 UTC +00:00,
 updated_at: Thu, 15 Aug 2019 20:02:47 UTC +00:00,
 sha1: "63347a46c0ca945f53613722a73c233484d642c8",
 origin: nil,
 retain_hours: nil,
 extension: "jpeg",
 thumbnail_width: 360,
 thumbnail_height: 360,
 etag: nil,
 secure: false,
 access_control_post_id: nil,
 original_sha1: nil>

OptimizedImage.where(upload_id: 20504).where(version: 2)

=> [#<OptimizedImage:0x000056366a01c1a0
  id: 95962,
  sha1: "5a32b5cc3e6f5c58d88a3c92a23076980a8ce840",
  extension: ".jpeg",
  width: 200,
  height: 200,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_200x200.jpeg",
  filesize: 28916,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a0741e8
  id: 95942,
  sha1: "ee353c9e23511b471e1a59c1f71a2ded3e366b1e",
  extension: ".jpeg",
  width: 20,
  height: 20,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_20x20.jpeg",
  filesize: 1270,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a074120
  id: 95943,
  sha1: "944fa9fc542a79a5c50394c75022bf84ace297e5",
  extension: ".jpeg",
  width: 30,
  height: 30,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_30x30.jpeg",
  filesize: 1952,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a074058
  id: 95944,
  sha1: "983490e58bed58c971ffa44e440b02ce3ea72bba",
  extension: ".jpeg",
  width: 40,
  height: 40,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_40x40.jpeg",
  filesize: 2695,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a07bf60

Так что, видимо, изображения есть, но они не отображаются. Видно только серый плейсхолдер аватара по умолчанию.

На уровне записей базы данных всё в порядке. При расследовании можно перейти к уровням выше.

Что вы получаете, когда вручную переходите по ссылкам на загруженные файлы, которые вы перечислили?

Если я добавлю /uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_200x200.jpeg (то есть) после URL моего Discourse, я получаю ошибку 404 — не найдено.

Значит, они не существуют? (Спрашиваю с надеждой :P)

Проверьте также некоторые URL-адреса файлов из /uploads/default/original, а не только из /uploads/default/optimized.

404 … Это означает, что вам нужно проверить папку uploads внутри /var/discourse/shared/standalone в файловой системе и найти, где находятся фактические старые файлы (если они существуют). Когда вы их найдете, попробуйте сравнить расположение с недавно загруженными файлами (теми, которые работают).

Вы также можете восстановить их из резервной копии вручную.

Спасибо за разъяснение.

Только что зашел туда, перепроверил: некоторые из перечисленных путей не существуют.

Странно то, что у меня есть люди, пытающиеся загрузить новые файлы, но и они не работают. Когда вы проверяете с помощью команд, которые вы мне дали, вы видите путь, которого тоже нет. Как Discourse «отображает» это? Потому что одно дело, что файлы отсутствуют (хотя резервная копия должна была их перенести), но другое — новые загрузки уходят в несуществующие пути?

Проверьте папку tombstone внутри папки uploads — не находятся ли там некоторые из отсутствующих файлов?

Единственная папка, которую я вижу внутри uploads, — это default… папка tombstone предназначена для устаревших файлов или что-то в этом роде?

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

Похоже, если вы каким-то образом измените изображение (даже просто сохранив его в другом формате в Photoshop), то сможете загрузить его снова.

Это нормальное поведение. Хэш файла данных хранится в базе данных для избежания дублирования изображений.

Что происходит, если вы загружаете изображение через редактор создания? Завершается ли загрузка? Появляется ли изображение в панели предпросмотра?

Если я напишу сообщение и добавлю к нему изображение, оно отобразится в панели предварительного просмотра и загрузка завершится. Да, это нормальное поведение.

Так на каком именно этапе изображение перестает отображаться?

Проверьте URL этого изображения, которое вы видите, и найдите его в файловой системе.

Проверьте URL изображений, которые не работают (через инструменты разработчика в браузере). В чем разница?

Возможно, они указывают на разные домены.

В первом сообщении я имел в виду именно аватары (через профиль пользователя), а во втором — редактор.

Таким образом, в обычном сообщении, если вы перетащите изображение или нажмёте кнопку «Загрузить изображение», всё будет работать без сбоев, как обычно.

Кратко:

  • Аватары не отображаются, показывается только заглушка.
  • Пользовательские эмодзи также не отображаются.
  • Изображения сайта (логотип и т. д.) тоже не показывались.
  • Если загружать изображения через редактор, всё работает нормально.
  • Если попытаться загрузить тот же аватар, который был до инцидента, это не сработает. Поведение следующее: загрузка произойдёт, но в поле выбора между буквой по умолчанию, Gravatar или загрузкой будет показан пустой квадрат. После подтверждения выбора и перезагрузки страницы вы увидите серую заглушку.

Также:

  • Папки Tombstone нет.
  • Старые изображения находятся в директориях (как показано в запросах, которые вы дали), которые не существуют.

Позвольте мне проверить вопрос с доменом. Как заметка: когда я искал информацию, я попробовал:

  • Запустить задачу CreateMissingAvatars через Sidekiq → Не удалось.
  • Пересобрать все посты (да, это довольно экстремально) → Не удалось.
  • Исходя из этой темы, так как я использовал другой домен (фактически поддомен) для тестирования восстановления из резервной копии, пока основной сайт был недоступен, я подумал, что возможно некоторые URL-адреса неверны, поэтому выполнил команду: discourse remap talk.foo.com talk.bar.com → Не удалось.

@Iceman

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

Очень интересно (и очень круто, на мой взгляд), как работает планировщик заданий Redis / Sidekiq, когда они запущены параллельно, но только одно «активно на стороне веб-интерфейса пользователя»:

Надеюсь, вам будет интересно прочитать эту короткую дискуссию с реальным примером. Она может дать небольшое представление о планировщике заданий Discourse, оптимизации изображений и аватарах в рамках нашей конфигурации:

Я большой поклонник того, как Discourse использует Redis / Sidekiq для планирования фоновых заданий; и считаю это одним из ключевых преимуществ и сильных сторон архитектуры ПО Discourse.

Примечание: Эти концепции также в различных тонких аспектах применимы к разным этапам процесса резервного копирования и восстановления, а также к другим процессам (зависящим от времени), поэтому полезно понимать, как и почему Sidekiq планирует задания в фоновом режиме.

Спасибо за информацию, @neounix, это очень помогает лучше понять «внутреннее устройство» Discourse с точки зрения «я изучаю Rails, чтобы помочь, но, черт возьми, это очень крутой учебный курс, пока пытаюсь исправить свою собственную установку» :stuck_out_tongue:

Сейчас я сосредоточен на Redis/Sidekiq, чтобы попытаться понять, почему некоторые встраивания не работают, так как я думаю, что это может быть связано с «Bake», но я не могу подписаться под этим, поскольку всё ещё нахожусь на этапе отладки (надеюсь).

Что касается моей проблемы здесь, благодаря @Overgrow я смог определить, что:

  • На самом деле процесс резервного копирования действительно скопировал файлы в резервную копию, но не восстановил их в установку Discourse. Исходя из статуса и/или исправлений моих других трёх проблем, возможно, мне потребуется восстановить другую резервную копию на другой установке и снова протестировать процесс резервного копирования, но это может быть проблемой для всех, пока неясно.

  • Из-за этого происходило странное поведение.

  • В итоге я открыл резервную копию и внедрил отсутствующие файлы в установку. Всё восстановилось без необходимости повторного «Bake».

Однако другие проблемы сохраняются (невозможность пересоздать контейнер данных, в котором я совсем не разбираюсь, и две проблемы, из-за которых я сосредоточился на Sidekiq и событиях, так как они могут быть решены именно так: некоторые Oneboxes (в частности, YouTube) не работают, и некоторые уведомления о «ложных» правках рекурсивно появляются у некоторых пользователей, хотя правок не было. Поэтому я думаю, что в новой установке могут быть проблемы с событиями, пытаюсь разобраться. :man_shrugging: