ruby-on-rails - 可以在 Thread::handle_interrupt block 之外异步处理 ruby​​ 异常吗?

标签 ruby-on-rails ruby multithreading rabbitmq

乍一看,我以为新的 ruby​​ 2.0 Thread.handle_interrupt 会解决我所有的异步中断问题,但除非我弄错了,否则我无法让它做我想做的事(我的问题在最后和标题中)。

从文档中,我可以看到如何避免在某个 block 中接收中断,将它们推迟到另一个 block 。这是一个示例程序:

duration = ARGV.shift.to_i

t = Thread.new do
  Thread.handle_interrupt(RuntimeError => :never) do
    5.times { putc '-'; sleep 1 }
    Thread.handle_interrupt(RuntimeError => :immediate) do
      begin
        5.times { putc '+'; sleep 1}
      rescue
        puts "received #{$!}"
      end
    end
  end
end

sleep duration
puts "sending"
t.raise "Ka-boom!"

if t.join(20 + duration).nil?
  raise "thread failed to join"
end

当使用参数 2 运行时,它输出如下内容:

--sending-
--received Ka-boom!

也就是说,主线程在两秒后向另一个线程发送了一个RuntimeError,但那个线程直到进入内部Thread.handle_interrupt才处理它> 阻止。

不幸的是,如果我不知道我的线程是在哪里创建的,我看不出这对我有什么帮助,因为我无法将它所做的一切都包装在一个 block 中。例如,在 Rails 中,我将如何包装 Thread.handle_interruptbegin...rescue...end block ?这不会因运行的网络服务器而有所不同吗?

我所希望的是一种注册处理程序的方法,就像 Kernel.trap 的工作方式一样。也就是说,我想指定上下文无关的处理代码,它将处理特定类型的所有异常:

register_handler_for(SomeExceptionClass) do 
 ... # handle the exception
end

引发这个问题的是 RabbitMQ gem bunny 如何使用 Thread#raise 向打开 Bunny::Session 的线程发送连接级错误。这些异常可能会出现在任何地方,我想做的就是记录它们,标记连接不可用,然后继续我的路。

想法?

最佳答案

Ruby 用 ruby​​ Queue 提供了这个功能对象(不要与 AMQP 队列混淆)。如果 Bunny 要求您在打开 Bunny::Session 之前创建一个 ruby​​ Queue,并且您将那个 Queue 对象传递给它,它将向其发送连接,那就太好了-级错误,而不是使用 Thread#raise 将其发送回任何地方。然后,您可以简单地提供自己的 Thread 来通过 Queue 消费消息。

可能值得深入了解 RabbitMQ gem 代码,看看您是否可以这样做,或者询问该 gem 的维护者。

在 Rails 中,这不太可能起作用,除非您可以建立一个服务器范围的线程来使用 ruby​​ 队列,这当然是特定于 Web 服务器的。我看不出如何从一个短暂的对象中做到这一点,例如Rails View 的代码,其中线程被重用,但 Bunny 不知道(或不关心)。

关于ruby-on-rails - 可以在 Thread::handle_interrupt block 之外异步处理 ruby​​ 异常吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21147545/

相关文章:

ruby-on-rails - 评估 :dependent => :destroy

ruby-on-rails - 在 Ruby 中重用 GraphQL 参数

ruby-on-rails - 无法在 Rails 3 中将 String 和 Fixnum 转换为 JSON

ruby-on-rails - 在模块中声明一个类

c - 限制 pthreads 中并发线程执行的数量

ruby-on-rails - "rake assets:precompile"给出 punc 错误

ruby-on-rails - 不允许的参数在 rails 4.0 中向 Devise 添加新字段

javascript - 使用 Rails 生成 Javascript 代码

c++ - 是否有 Windows API 来自动设置 16 字节数组?

c# - 在 windows 窗体中实现加载器,如 web 应用程序