4

update每当调用控制器中的操作(或每当更新我的模型时),我都想发出服务器发送的事件。我目前watch在带有虚拟发射器的同一个控制器中有一个工作动作:

def watch
    self.response.headers["Content-Type"] = "text/event-stream"
    self.response.headers["Last-Modified"] = Time.now.ctime.to_json
    self.response_body = Enumerator.new do |y|
        100.times do |i|
            sleep 5
            y << ["event: message", "data: #{i}\n\n"].join("\n")
        end
    end
    # TODO catch IO error when client disconnects
end

如何获得一个在update被调用时产生/返回值的可枚举对象?(注意:它不一定是一个 Enumerable;但它必须响应#each这种流技术才能工作。)从某种意义上说,我想我正在尝试在 Rails 中实现一个事件驱动的架构。

我知道Observable但我不知道如何让我的观察者可以根据需要进行枚举......或者如何在没有循环和睡眠计时器的情况下将观察者放入枚举器(如上)。

这样做的目的是将对数据库所做的更改发送给当前登录的所有其他用户,以便每个用户始终拥有数据库的当前反映。

谢谢-

4

2 回答 2

1

这不一定是最好的解决方案,但我最终创建了一个消息队列,如下所示:我在我的数据库中创建了一个新表(“SSE”),在我想要观察的模型中,我添加了回调:

class MyModel < ActiveRecord::Base
  after_save :queue_sse
  after_delete :queue_sse
  # ...
  private
    def queue_sse
      connected_users.each do |user|
        SSE.create(:changed_record_id => this.id, :user_id => user)
      end
    end
end

然后在watch动作中:

def watch
  connected_users << current_user # pseudo for a mutex-synched accessor
  self.response.headers["Content-Type"] = "text/event-stream"
  self.response.headers["Last-Modified"] = Time.now.ctime.to_json
  self.response_body = Enumerator.new do |y|
    loop do
      sleep 5
      ActiveRecord::Base.uncached do
        updates = SSE.find_all_by_user_id(current_user)
        updates.each do |update|
          puts "update found: #{update.id}\n"
          y << ["event: message", "data: #{update.id}\n\n"].join("\n")
          update.destroy
        end
      end
    end
  end
  # TODO add error catching, and on IOError, remove the current_user
end

不过,这会对数据库造成很大影响。它可能应该建立在 memcached、互斥类变量或类似的基础上。

(注意——当然需要线程,例如config.threadsafe!和线程服务器。)

于 2012-09-20T22:23:37.747 回答
1

我创建了一个 gem,它允许您使用 SSE“广播”事件。它允许您从更新操作将数据推送到连接的客户端。它被称为 R4S ( https://github.com/biggihs/r4s )

例子

def update
  #do some updating
  R4S.push_data("key",{data:"data"},:event=>"SomeJsEvent")     
end

这会将数据推送到连接到 sse 流“key”的所有浏览器

于 2012-11-13T11:14:06.067 回答