ActiveRecord::StatementInvalid, когда процесс получает SIGTERM?

В моем приложении Rails у меня есть скрипт, который обновляет некоторые записи в базе данных. Когда я отправляю SIGTERM, чтобы убить сценарий, он время от времени получает этот сигнал, пока ActiveRecord выполняет запрос. Это приводит к возникновению исключения ActiveRecord::StatementInvalid.

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


person readonly    schedule 13.02.2009    source источник
comment
Есть ли что-то еще, что вы ищете, чтобы закрыть этот вопрос?   -  person wuputah    schedule 25.08.2010


Ответы (3)


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

 Signal.trap("TERM") do
   Kernel.exit!
 end

Причина, по которой вы получаете ошибку StatementInvalid, заключается в том, что Ruby обрабатывает сигнал, вызывая исключение SIGTERM в месте текущего выполнения. ActiveRecord перехватывает исключение и повторно выдает его как StatementInvalid. Установив обработчик сигнала, Ruby выполнит ваш обработчик, а не вызовет исключение.

Дополнительные сведения см. в документации по Ruby Signal.

person wuputah    schedule 16.02.2009
comment
Исправлено, необходимо использовать Kernel.exit! чтобы это работало. Доказательство на примере: gist.github.com/66735 - person wuputah; 19.02.2009
comment
Предполагая, что этот тип выхода является нормальным, вы, вероятно, захотите Kernel.exit! true. Таким образом, процесс завершится со статусом 0. - person johnf; 28.07.2011

Похоже, что этот «скрипт» является внешним по отношению к приложению Rails (script/runner или похожему?), поэтому, возможно, вы можете разделить «обработчик сигналов» и «работник»? Например, можете ли вы разветвить дочерний процесс/поток/волокно/... для обновления базы данных и сигнализировать родителю указать «остановить сейчас»? Конечно, тогда родитель должен будет «сигнализировать» ребенку, чтобы он прекратил использовать какой-либо соответствующий механизм (не SIGTERM ;-)).

person Martin Carpenter    schedule 14.02.2009

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

time_to_die=false

# Prevent abrupt stopping of the daemon.
Signal.trap("TERM") { time_to_die=true; "SIG_IGN" }   

loop {
  .
  .
  exit_gracefully if time_to_die
  .
  .
}

def exit_gracefully
   #Cleaning up..
   $log.log "#{Time.now} TERM signal received. Exiting.."
   $db.close
   exit
 end
person Jasim    schedule 01.02.2010