Как заставить Bluepill перезапустить работников Resque только после достижения безопасного статуса

Допустим, это мой рабочий:

class FooWorker
  @queue = :foo

  def self.perform
    User.all.each do |u|
      ...
      Do Long Operations (Unsafe to kill)
      ...

      # Here it's safe to break the worker and restart
    end
  end
end

Я завожу это в Resque Scheduler, и это мой конф Bluepill:

...
app.process(process_name) do |process|
  process.group         = "resque"
  process.start_command = "rake environment resque:work QUEUE=foo RAILS_ENV=production"
  ...
  process.stop_signals  = [:quit, 5.seconds, :term, 1.minute, :kill]
  process.daemonize     = true

  process.start_grace_time = 30.seconds
  process.stop_grace_time  = 80.seconds

  process.monitor_children do |child_process|
    child_process.stop_command = "kill -QUIT {{PID}}"

    child_process.checks :mem_usage, :every => 30.seconds, :below => 500.megabytes, :times => [3,4], :fires => :stop
  end
end
....

Я бы хотел, чтобы Bluepill или Resque подождали, пока он не достигнет "безопасного" блока для перезапуска или выключения. Как этого добиться?

1 ответ

Попробуйте это так:

1) Установите Resque, чтобы грациозно убивать детей в TERM/INT с помощью new_kill_child метод по настройке TERM_CHILD а также RESQUE_TERM_TIMEOUT Переменные env при запуске:

process.start_command = "rake environment resque:work QUEUE=foo RAILS_ENV=production TERM_CHILD=1 RESQUE_TERM_TIMEOUT=20.0"

Значение по умолчанию для RESQUE_TERM_TIMEOUT 4 секунды.

Это заставит рески отправить TERM-сигнал ребенку, дождаться RESQUE_TERM_TIMEOUT и если ребенок все еще бежит, убейте его. Обязательно

а) установите этот тайм-аут достаточно большим для завершения критического раздела,

б) настроить время ожидания Bluepill TERM в process.stop_signals быть немного больше чем RESQUE_TERM_TIMEOUT не убивать работника, пока он ожидает завершения дочернего процесса в критической секции.

2) Обработайте сигнал TERM в дочернем процессе, чтобы аккуратно остановить:

class FooWorker
  class << self
    attr_accessor :stop
  end

  @queue = :foo
  def self.perform
    User.all.each do |u|
      ...
      Do Long Operations (Unsafe to kill)
      ...

      # Here it's safe to break the worker and restart
      return if FooWorker.stop
    end
  end
end

trap('TERM') do
  FooWorker.stop = true
end
Другие вопросы по тегам