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

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

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

3 ответа

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

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

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

См. Документацию Ruby Signal для получения дополнительной информации.

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

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

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

Другие вопросы по тегам