Медленный скрипт пересборки, чтобы не перегружать ваш сервер

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

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

# slow_rebake_resumer_ultralow.rb
# Возобновляет постановку задач перепечки с определённой точки и отправляет их
# напрямую в очередь :ultra_low.
# Запускать внутри контейнера командой: rails runner slow_rebake_resumer_ultralow.rb

# --- Настройки ---
BATCH_SIZE = 500
SLEEP_DURATION = 5
# --- Точка старта с вашего последнего обновления ---
last_processed_id = 0 
# --------------------

start_time = Time.now
total_posts = Post.count

puts "Возобновление и постановка задач перепечки для #{total_posts} постов в очередь :ultra_low..."
puts "Начинаем с поста ID #{last_processed_id}."
puts "---"

loop do
  # Эффективный поиск следующей партии постов для обработки
  posts_to_enqueue = Post.where("id > ?", last_processed_id).order(id: :asc).limit(BATCH_SIZE)

  # Выход из цикла, если постов больше нет
  break if posts_to_enqueue.empty?

  posts_to_enqueue.each do |post|
    begin
      # Определение всех опций в одном хэше, включая целевую очередь
      options = {
        post_id: post.id,
        cook: true,
        bypass_bump: true,
        queue: :ultra_low
      }

      # Постановка задачи с правильным, проверенным синтаксисом
      Jobs.enqueue(:process_post, options)

    rescue => e
      puts "!!! ОШИБКА при постановке задачи для поста ID #{post.id}: #{e.message}"
    end
  end

  # Обновляем позицию на ID последнего поста в текущей партии
  last_processed_id = posts_to_enqueue.last.id
  
  # Получаем более точный счётчик для отчёта о прогрессе
  enqueued_count = Post.where("id <= ?", last_processed_id).count

  # --- Отчёт о прогрессе ---
  percentage = (enqueued_count.to_f / total_posts * 100).round(2)
  elapsed_minutes = ((Time.now - start_time) / 60).round(2)

  puts "Поставлено до поста ID #{last_processed_id}. Всего поставлено: ~#{enqueued_count} / #{total_posts} (#{percentage}%)"
  puts "Прошло времени (эта сессия): #{elapsed_minutes} минут."
  puts "Задачи отправляются в очередь :ultra_low."

  # Пауза между партиями для снижения нагрузки
  if enqueued_count < total_posts
    puts "Пауза на #{SLEEP_DURATION} секунд..."
    sleep(SLEEP_DURATION)
    puts "---"
  end
end

puts "\nВсе оставшиеся задачи перепечки успешно поставлены в очередь :ultra_low!"

Я почти уверен, что процесс, выполняющий практически то же самое, уже работает постоянно, и об этом упоминается в скрипте восстановления. Но, возможно, вы запускали миграцию на рабочем сервере и не обратили на это внимания…

Да, есть. Я не импортировал стандартный скрипт миграции. Позже расскажу об этом подробнее, когда пользователи перестанут жаловаться на бесконечную прокрутку и в целом на загроможденный, неудобный интерфейс Discourse. :upside_down_face:

Но в целом иногда может потребоваться полная пересборка, например, смена домена, выполнение поиска и замены и т.д.

Извините за всплытие темы, у меня схожая ситуация с моим Discourse.

Есть ли какие-то советы, как запустить этот скрипт?

Где создать скрипт и как его вызвать?

Заранее спасибо.

Создайте файл slow_rebake_resumer_ultralow.rb в директории tmp внутри общей директории и вставьте в него весь код.

Затем выполните этот файл один раз внутри контейнера с помощью команды rails runner slow_rebake_resumer_ultralow.rb.

Наблюдайте за прогрессом по адресу yousite.com/sidekiq.