我正在创建一个后台脚本,该脚本使用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
答案 0 :(得分:4)
由于您在线程中导致异常,因此应将Thread.abort_on_exception设置为true
,否则将无法正确引发这些错误。
答案 1 :(得分:0)
你根本不需要在这里使用Thread.new,事实上,这样做并不是线程安全的(eventmachine本身不是线程安全的,除了EM :: Queue,EM :: Channel和EM.schedule )。
如果你想在执行中做同步事情,并且你必须拥有该线程,那么你需要通过EM.schedule调用h.send,例如:
EM.schedule { h.send("welcome!") }
如果你必须以这种方式拥有该线程,那么,你想要从你自己产生的线程中捕获异常。然后你应该自己停止并关闭,或者只是在主(eventmachine)线程中重新启动:
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。