为什么在赛璐珞中出现错误`Celluloid :: Condition发出虚假信号?

时间:2015-07-07 17:47:38

标签: ruby asynchronous celluloid

我正在尝试等待异步代码,这是片段:

condition = Celluloid::Condition.new   
Rails.logger.debug "Sending RPC request to #{subject}"
NATS.start uri: ENV['NATS_SERVER'] do 
  Rails.logger.debug "Connected to #{ENV['NATS_SERVER']}"
  sid = NATS.request(subject,msg) do |response|
    Rails.logger.debug "Assigning response"
    condition.signal response
    NATS.stop
  end
  NATS.timeout(sid, 1) do
    NATS.stop
    condition.signal ASYNC_ERROR
    raise "One second timeout waiting for a NATS RPC reply from #{subject}"
  end
end

result = condition.wait
if result = ASYNC_ERROR
  raise "Error in RPC call"
else
  return result
end

我收到异常Celluloid::Condition signaled spuriously,但没有额外的信息,我不明白为什么会造成这种情况,https://github.com/celluloid/celluloid/wiki/Conditions不提供更多信息。

为什么会造成这种情况,我该如何解决?

2 个答案:

答案 0 :(得分:1)

使用条件来回答你的问题,就像你陈述的问题一样。

在演员范围内:

class Nats
  include Celluloid

  def initialize
    @condition = Celluloid::Condition.new
  end

  def start
    Rails.logger.debug "Sending RPC request to #{subject}"
    NATS.start uri: ENV['NATS_SERVER'] do 
      Rails.logger.debug "Connected to #{ENV['NATS_SERVER']}"
      sid = NATS.request(subject,msg) do |response|
        Rails.logger.debug "Assigning response"
        @condition.signal response
        NATS.stop
      end
      NATS.timeout(sid, 1) do
        NATS.stop
        @condition.signal ASYNC_ERROR
        raise "One second timeout waiting for a NATS RPC reply from #{subject}"
      end
    end
  end

  def value
    @condition.wait
  end
end

nats = Nats.new
nats.async.start

result = nats.value
if result = ASYNC_ERROR
  raise "Error in RPC call"
else
  return result
end

这种情况测试得更少,但如果您不像我的其他答案那样使用Future,则应该向您展示基本方法。

答案 1 :(得分:0)

您的情况不是在演员的背景下运作。请注意,在示例中,使用了actor。可以避免使用actor上下文,但这是非常不同的,并且是你收到的错误的根源。

如果你不想在演员中实现这个,就像在例子中一样,这是一种你可以在没有演员的情况下实现的方法:

使用Celluloid::Future(即使嵌套async次调用)

nats = Celluloid::Future.new {
    blocker = Queue.new
    Rails.logger.debug "Sending RPC request to #{subject}"
    NATS.start uri: ENV['NATS_SERVER'] do 
        Rails.logger.debug "Connected to #{ENV['NATS_SERVER']}"
        sid = NATS.request(subject,msg) do |response|
            Rails.logger.debug "Assigning response"
            NATS.stop
            blocker << response
        end
        NATS.timeout(sid, 1) do
            NATS.stop
            blocker << nil
            #de "One second timeout waiting for a NATS RPC reply from #{subject}"
        end
    end
    blocker.pop || raise ASYNC_ERROR
}

begin
    result = nats.value
rescue ASYNC_ERROR
    raise "Error in RPC call"
rescue => ex
    #de Other exception
else
    return result
end

以上是用于实现async响应收集的一个简单示例,具有异常处理功能。这是许多可能方法中的一个例子。