0

我正在创建一个后台脚本,该脚本使用 EventMachine 通过 WebSockets 连接到服务器。该脚本将使用 DelayedJob 或 Resque 运行。我已经能够让它与 WebSockets 服务器对话并发送消息,但是只要在 EventMachine 循环中引发错误,它就不会使脚本崩溃——这是应该发生的(以及我需要发生的) . 我不必使用 EventMachine,因为我只发送 WebSocket 消息而不接收它们 - 但我很想在这方面提供任何帮助 :) 谢谢!

#!/usr/bin/env ruby
require 'rubygems'
require 'eventmachine'
require 'em-http'

class Job
  include EventMachine::Deferrable

  def self.perform
    job = Job.new
    EventMachine.run {
      http = EventMachine::HttpRequest.new("ws://localhost:8080/").get :timeout => 0

      http.errback { puts "oops" }
      http.callback {
        puts "WebSocket connected!"
        http.send("Hello watcher")
      }

      http.stream { |msg| }
      job.callback { puts "done" }
      Thread.new { 
        job.execute(http)
        http.close
        EventMachine.stop
      }
    }
  end

  def execute(h)
      sleep 1
      puts "Job Runner!"
      h.send("welcome!")
      sleep 2
      asdsadsa # here I am trying to simulate an error
      sleep 1
      h.send("we are all done!")
      sleep 1
      set_deferred_status :succeeded
  end
end

Job.perform
4

2 回答 2

4

由于您在线程内引起异常,因此应将Thread.abort_on_exception设置为,true否则将无法正确引发这些错误。

于 2010-11-16T18:34:18.767 回答
0

在这里你根本不需要使用 Thread.new,实际上这样做不是线程安全的(eventmachine 本身不是线程安全的,除了 EM::Queue、EM::Channel 和 EM.schedule)。

如果你想在执行中做同步的事情,并且你必须有那个线程,那么,你会想通过 EM.schedule 调用 h.send,例如:

EM.schedule { h.send("welcome!") }

如果您必须以这种方式拥有该线程,那么您希望从您自己生成的线程中捕获异常。然后,您应该自行停止和关闭,或者只是在主(事件机器)线程中重新启动:

EM.run do
  thread = Thread.new do
    raise 'boom'
  end
  EM.add_periodic_timer(0.1) { thread.join(0) }
end

如果合适的话,上面的模式可以很容易地在周期性计时器中枚举一个线程数组。

最后,请注意异常冒泡(正确的异常报告)仅在 EventMachine > 1.0 中支持,该版本仍处于测试阶段。要在发生异常时获得可用的回溯gem install eventmachine --pre,或者更好,请使用 Github 存储库中的 master。

于 2012-04-25T05:55:57.253 回答