当进程收到 SIGTERM 时 ActiveRecord::StatementInvalid?
在我的 Rails 应用程序中,我有一个脚本可以更新数据库中的一些记录。 当我发送 SIGTERM 来终止脚本时,它偶尔会在 ActiveRecord 执行查询时收到该信号。 这会导致引发 ActiveRecord::StatementInvalid 异常。
我想捕获当它们是 SIGTERM 的结果时发生的 StatementInvalid 异常并退出脚本。 我如何判断 StatementInvalid 是由于信号而不是其他原因而发生的?
In my Rails app, I have a script that updates some records in the database. When I send a SIGTERM to kill the script, it occasionally receives that signal while ActiveRecord is executing a query. This leads to an ActiveRecord::StatementInvalid exception being raised.
I'd like to catch StatementInvalid exceptions that occur when they're they're the result of a SIGTERM and exit the script. How can I tell that a StatementInvalid is occurring because of a signal and not for some other reason?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果你捕获 TERM 信号,我相信你会避免异常。 您可以在脚本的开头执行此操作(或者实际上在任何地方执行此操作,但只需执行一次)。
出现 StatementInvalid 错误的原因是 Ruby 通过在当前执行位置引发 SIGTERM 异常来处理信号。 ActiveRecord 正在捕获异常并将其作为 StatementInvalid 重新抛出。 通过设置信号处理程序,Ruby 将执行您的处理程序而不是引发异常。
有关更多信息,请参阅 Ruby Signal 文档。
If you trap the TERM signal, I believe you will avoid the exception. You can do this at the beginning of your script (or really anywhere for that matter, but you only need to do it once).
The reason you get the StatementInvalid error is Ruby handles the signal by raising a SIGTERM exception at the place of current execution. ActiveRecord is catching the exception and rethrowing it as StatementInvalid. By setting a Signal handler, Ruby will execute your handler instead of raising an exception.
See the Ruby Signal documentation for more information.
听起来这个“脚本”是Rails应用程序外部的(
script/runner
或类似的?),所以也许你可以将“信号处理程序”和“worker”解耦? 例如,您可以分叉一个子进程/线程/光纤/...来执行数据库更新,并向父进程发出信号以指示“立即停止”吗? 当然,父级必须“通知”子级停止使用某种适当的机制(不是SIGTERM
;-))。It sounds like this "script" is external to the Rails app (
script/runner
or similar?), so perhaps you can decouple the "signal handler" and "worker"? Eg can you fork a child process/thread/fiber/... to do the database update, and signal the parent to indicate "stop now"? Of course the parent will then have to "signal" the child to stop using some appropriate mechanism (notSIGTERM
;-)).这不是OP的准确答案,但是,您可以控制退出点 - 程序仅在到达您定义的退出点后才会退出。
This is not an exact answer to the OP, however, you can control the exit point - the program will exit only after reaching the exit point defined by you.