Запустите или убедитесь, что задержка задания работает при перезапуске приложения / сервера

StackOverflow https://stackoverflow.com/questions/2580871

Вопрос

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

В настоящее время, лучший способ, которым я могу подумать, чтобы гарантировать, что демон Delayed_job всегда работает, это добавить инициализатор в наше приложение Rails, которое проверяет, работает ли демон. Если он не работает, то инициализатор запускает демону, в противном случае он просто оставляет.

Следовательно, вопрос, как мы обнаруживаем, что демон delayed_job работает изнутри скрипта? (Мы должны быть в состоянии запустить демону довольно легко, бит, я не знаю, как обнаружить, если он уже активен).

У кого-нибудь есть идеи?

С уважением, Берни

Исходя из ответа ниже, это то, что я придумал. Просто положите его в конфигурацию / инициализаторы, и вы все набор:

#config/initializers/delayed_job.rb

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid"

def start_delayed_job
  Thread.new do 
    `ruby script/delayed_job start`
  end
end

def process_is_dead?
  begin
    pid = File.read(DELAYED_JOB_PID_PATH).strip
    Process.kill(0, pid.to_i)
    false
  rescue
    true
  end
end

if !File.exist?(DELAYED_JOB_PID_PATH) && process_is_dead?
  start_delayed_job
end
Это было полезно?

Решение

Проверьте наличие существования файла PID DAEMONS (File.exist? ...). Если это там, а, предположим, что он работает, еще запустите его.

Другие советы

Еще несколько идей очистки: «начало» не нужна. Вы должны спасти «нет такого процесса», чтобы не пожарить новые процессы, когда что-то еще идет не так. Спасите «Нет такого файла или каталога», а также упростить условие.

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid"

def start_delayed_job
  Thread.new do 
    `ruby script/delayed_job start`
  end
end

def daemon_is_running?
  pid = File.read(DELAYED_JOB_PID_PATH).strip
  Process.kill(0, pid.to_i)
  true
rescue Errno::ENOENT, Errno::ESRCH   # file or process not found
  false
end

start_delayed_job unless daemon_is_running?

Имейте в виду, что этот код не будет работать, если вы начнете более одного работника. И проверить аргумент «-M» сценария / задержки_JOB, который порождает процесс монитора вместе с демонами (ыми).

Спасибо за решение, указанное в вопросе (и ответ, который вдохновил его :-)), это работает для меня, даже с несколькими работниками (Rails 3.2.9, Ruby 1.9.3P327).

Это беспокоит меня, что я мог бы забыть перезапустить задержку_JOB после того, как некоторые изменения в Lib например, заставляя меня отлаживать часами, прежде чем понимать, что.

Я добавил следующее на мой script/rails Файл Чтобы разрешить код, указанный в вопросе, чтобы выполнить каждый раз, когда мы начнем Rails, но не каждый раз, когда начинается работник:

puts "cleaning up delayed job pid..."
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid',  __FILE__)
begin
  File.delete(dj_pid_path)
rescue Errno::ENOENT # file does not exist
end
puts "delayed_job ready."

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

Обратите внимание, что если вы используете Unicorn, вы можете добавить тот же код для config/unicorn.rb перед before_fork вызов.

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

Я создал файл script/start_delayed_job.rb С контентом:

puts "cleaning up delayed job pid..."
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid',  __FILE__)

def kill_delayed(path)
  begin
    pid = File.read(path).strip
    Process.kill(0, pid.to_i)
    false
  rescue
    true
  end
end

kill_delayed(dj_pid_path)

begin
  File.delete(dj_pid_path)
rescue Errno::ENOENT # file does not exist
end

# spawn delayed
env = ARGV[1]
puts "spawing delayed job in the same env: #{env}" 

# edited, next line has been replaced with the following on in order to ensure delayed job is running in the same environment as the one that spawned it
#Process.spawn("ruby script/delayed_job start")
system({ "RAILS_ENV" => env}, "ruby script/delayed_job start")

puts "delayed_job ready."

Теперь я могу потребовать этого файла в любом месте, в том числе «скрипт / Rails» и «Config / unicorn.rb», делая:

# in top of script/rails
START_DELAYED_PATH = File.expand_path('../start_delayed_job',  __FILE__)
require "#{START_DELAYED_PATH}"

# in config/unicorn.rb, before before_fork, different expand_path
START_DELAYED_PATH = File.expand_path('../../script/start_delayed_job',  __FILE__)
require "#{START_DELAYED_PATH}"

Не здорово, но работает

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

Вы могли запланировать cron Задачи, которые периодически бегают, чтобы начать задание работы. Поскольку DJ относится к запуску команд, как NO-OPS, когда работа уже работает, она просто работает. Этот подход также заботится о том случае, когда DJ умирает по какой-то причине, кроме перезапуска хоста.

# crontab example 
0 * * * * /bin/bash -l -c 'cd /var/your-app/releases/20151207224034 && RAILS_ENV=production bundle exec script/delayed_job --queue=default -i=1 restart'

Если вы используете драгоценный камень, как whenever Это довольно просто.

every 1.hour do
  script "delayed_job --queue=default -i=1 restart"
  script "delayed_job --queue=lowpri -i=2 restart"
end
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top