gpt4 book ai didi

ruby - 在进行数据库调用的线程中使用 ruby​​ 超时

转载 作者:数据小太阳 更新时间:2023-10-29 07:16:24 24 4
gpt4 key购买 nike

我正在使用 Ruby 1.9.2。

我有一个正在运行的线程,它定期调用数据库。调用可能会很长,有时(由于各种原因)数据库连接会消失。如果它真的消失了,线程就会永远静静地卡在那里。

因此,我想将其全部包装在超时中以处理此问题。问题是,在第二次应该调用超时时(总是第二次),它仍然只是挂起。超时永远不会生效。我知道这个问题在 1.8 中存在,但我被引导相信 timeout.rb 在 1.9 中有效。

t = Thread.new do
while true do
sleep SLEEPTIME
begin
Timeout::timeout(TIMEOUTTIME) do
puts "About to do DB stuff, it will hang here on the second timeout"
db.do_db_stuff()
process_db_stuff()
end
rescue Timeout::Error
puts "Timed out"
#handle stuff here
end
end
end

知道为什么会发生这种情况以及我能做些什么吗?

最佳答案

一种可能是您的线程没有挂起,它实际上死了。这是您应该做的事情,以弄清楚发生了什么。在创建工作线程之前添加:

Thread.abort_on_exception = true

当在您的线程中引发一个从未被捕获的异常时,您的整个进程将终止,并且您可以看到引发了哪个异常。否则(这是默认设置),您的线程将被终止。

如果事实证明这不是问题,请继续阅读...

Ruby 的超时实现非常天真。它设置一个单独的线程休眠 n 秒,然后盲目地在原始线程内引发超时异常。

现在,原始代码实际上可能位于 rescueensure block 的中间。在这样的 block 中引发异常将静默中止任何类型的清理代码。这可能会使超时的代码处于不正确的状态。

很难判断这是否正是您的问题,但看看数据库处理程序如何执行相当多的锁定和异常处理,这很有可能。 Here's an article that explains the issue in more depth .

有什么方法可以使用数据库库的内置超时处理吗?它可能在较低级别上实现,而不是使用 Ruby 的超时实现。

一个简单的替代方法是在单独的进程中安排数据库调用。每次执行繁重的数据库提升操作时,您都可以 fork 主进程。或者您可以设置一个简单的 cronjob 来执行执行它的脚本。如果您需要与主线程通信,这将稍微困难一些。如果您需要关于哪个选项可能适合您的需求的任何建议,请留下更多详细信息。


根据您的评论,该线程即将终止。这可能是您可能无法修复的库或应用程序代码中的错误。如果您希望捕获由数据库处理代码生成的任意错误并随后重试,您可以尝试如下操作:

t = Thread.new do
loop do
sleep INTERVAL
begin
# Execute database queries and process data
rescue StandardError
# Log error or recover from error situation before retrying
end
end
end

您还可以在 rescue block 中使用 retry 关键字立即重试,但您可能应该保留一个计数器以确保您不会意外无限期地重试不可恢复的错误不断发生。

关于ruby - 在进行数据库调用的线程中使用 ruby​​ 超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7651742/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com