Migrate_from_s3 problems

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

Кроме того, при указании max имеет смысл подробно описывать, что именно обрабатывается, в целях отладки. Поэтому я хочу сделать вывод подробным, если max не равен nil — это позволит пользователям проверять процесс перед продолжением, так как это основной сценарий использования данной работы.

Я думаю, что буду передавать max как первый аргумент, а опциональный limit — как второй, потому что max действительно является наиболее важным параметром; limit же нужен лишь для того, чтобы сделать «один запрос» дешевле.

Второй вопрос касается не-загрузок: загрузок. Более года назад я пытался загрузить видео на сайт Discourse, к которому присоединился, пока путался в попытках разобраться, как написать миграцию с Google+ на Discourse, и увидел, что сгенерированная ссылка выглядела так: https://#{SiteSettings.absolute_base_url}/original/3X/b/a/ba9e06ebc2f4397f26793bb5cd4e169308dd371d.mp4.

Сегодня же при загрузке видео я получаю что-то вроде: ![file_example_MP4_480_1_5MG|video](upload://caJ9ykkpshw3PFK4464VUIPWJ4l.mp4).

По крайней мере, в моём последнем тесте migrate_from_s3 полностью исказил эти URL-адреса, превратив их даже не в URL, так что это определённо нужно исправить. Затем, я считаю, что на практике эта задача вряд ли столкнётся с ![text](non-upload-url-to-migrate), поэтому на первом этапе я хочу просто добавить разметку ссылки вокруг магического протокола upload, вместо того чтобы заставлять регулярное выражение обрабатывать оба случая, что ещё больше усложнило бы его чтение. Хотя я могу передумать.

Похоже, что тег video или audio добавляется в JavaScript через соответствие регулярному выражению, поэтому мне придётся скопировать регулярные выражения из app/assets/javascripts/discourse/app/lib/uploads.js в задачу, чтобы правильно их идентифицировать. Я включу исходный код регулярных выражений, чтобы следующий человек, который их найдёт, знал, откуда их обновлять. :stuck_out_tongue:

Сегодня вечером я выделил время на эту работу и начал работу над черновиком PR. Он ещё не завершён; я знаю, что в нём остались ошибки. На данный момент я не изменил поведение для URL-адресов псевдопротокола upload: (обычно для изображений), хотя добавил проверку на корректность.

Благодаря изменениям в этом PR я успешно мигрировал как обычные загрузки псевдопротокола upload:, так и видео, которые в настоящее время явно ссылаются на S3 (в моём случае — на DigitalOcean Spaces). Я использую это для изменения только одного сообщения за раз с помощью следующей команды:

bin/rake uploads:batch_migrate_from_s3[1,1000]

Обратите внимание, что эта команда не перейдёт дальше первых 1000 сообщений, возвращаемых somewhat случайно из запроса к базе данных; низкий лимит установлен лишь для ускорения выполнения запроса при миграции одного сообщения за раз, проверке корректности поведения этого сообщения и последующем повторном запуске для поиска следующего. Эта команда работает таким образом только с моим текущим PR!

Я продолжаю добавлять диагностический вывод по мере работы над этим и начинаю думать, что это важно не только для разработки. Я наблюдаю множество временных сбоев загрузки из DigitalOcean Spaces, когда часть файлов в сообщении мигрируется, а часть — нет. В оригинале это просто печатает . и продолжает работу, затем говорит Done, но на самом деле задача не выполнена. Мне пришлось сделать около пяти-шести проходов по одному сообщению, прежде чем все файлы были мигрированы. (Я не считал, потому что сначала думал, что отлаживаю локальную ошибку.) Я ожидаю, что мне придётся запускать эту миграцию неоднократно с тем же лимитом, пока диагностические данные не станут чистыми. Поэтому я делаю подробный вывод прогресса только если установлен max, но вывожу полезные предупреждающие сообщения в любом случае.

В настоящее время я использую следующий обходной путь для периодических сбоев загрузки в Discourse Spaces, который на практике значительно повысил мой процент успеха (трёх повторных попыток оказалось вполне достаточно для сотен мигрированных сообщений).

https://github.com/johnsonm/discourse/commit/7dfac12a2ea6ec04ba4e0616b4e0dbd1d806cff7

Также я обнаружил, что somehow у нас оказались видео больше установленного мной лимита при импорте с Google+. Мне пришлось временно увеличить SiteSettings.max_image_size_kb и SiteSettings.max_attachment_size_kb во время одноразовой миграции нескольких видео с избыточным размером, хотя мне неясно, как они вообще оказались на сайте. Я не хочу ломать их сейчас… Не знаю, была ли ошибка, позволявшая загружать файлы избыточного размера, в моём скрипте импорта, в Discourse или просто в моей памяти о том, какие изменения я вносил в настройки со временем. :wink:

Поскольку значительная часть того, что я мигрирую, была импортирована с Google+, некоторые мои сообщения не прошли текущие проверки валидации. Я получил несколько ошибок Unhandled failure: Validation failed: Sorry, new users can only put one image in a post и сначала не понял, почему они не повторяются. Оказалось, что загрузки успешно перемещены на локальное хранилище, и все они использовали псевдопротокол upload:, поэтому сырое содержимое не изменилось. Однако post.save! всё равно завершался ошибкой валидации, что предотвращало вызов post.rebake!, поэтому у меня есть несколько сообщений из 30 тысяч с изображениями, которые требуют повторной обработки; к сожалению, у меня нет записи о том, какие именно это сообщения. Теперь я перешёл на post.save!(validate: false) как ещё одно исправление, так что эта конкретная проблема больше не должна возникать. Я очень рад, что миграция начала прерываться при необработанных ошибках, иначе это могло бы нанести гораздо больший ущерб, чем несколько сообщений.

Чтобы мой сайт оставался работоспособным, включая отправку уведомлений, во время выполнения миграции, я не хочу перегружать очереди Sidekiq. Я знаю, что именование — одна из двух самых сложных задач в информатике, наряду с инвалидацией кэша и ошибками off-by-one, но я предлагаю использовать переменную окружения DISCOURSE_MIGRATION_MAX_ENQUEUED для ограничения общего числа заполненных слотов очереди (не слотов задач), которые могут быть заняты при переходе к миграции следующего элемента после rebake во время миграции, чтобы избежать перегрузки очередей и обеспечить продолжение работы сайта. У меня есть патч, добавляющий это значение по умолчанию равным нулю для всех операций повторной обработки сообщений в lib/tasks/uploads.rake. Я использую это в своей производственной миграции.

https://github.com/discourse/discourse/blob/59a761851b9c8786d3a9692f8c595372b0534f77/lib/tasks/uploads.rake

4 лайка