2

我希望为利用 Sinatra 的内部项目构建一个简单的 RESTful 通知系统。我过去曾使用 EventMachine 频道来订阅/发布事件,但在我之前的所有案例中,我都直接使用 EventMachine。

有谁知道是否可以从 Sinatra 应用程序或什至从某些 Rack 中间件创建、订阅和发布到 EventMachine 通道(在 Thin 中运行)?

4

2 回答 2

2

看看async_sinatra

基本上,要在 Thin 中运行时使用 EventMachine,您需要让它知道您想要异步处理请求。Rack 协议在设计上是同步的,Thin 期望在处理程序返回时完成请求。有一些方法可以让 Thin 意识到您想要异步处理请求(有关如何处理的示例,请参见think_async ),而async_sinatra使这变得非常容易。

于 2011-04-22T17:58:45.230 回答
1

Bryan,您可以使用 em-http-request 库 (https://github.com/igrigorik/em-http-request),这将允许您引用在 A. 同一服务器、B 上运行的特定 EventMachine 应用程序. 一个不同的服务器,或者 C. 任何你想要的地方。

require 'eventmachine'
require 'em-http-request'
require 'sinatra/base'
require 'thin'

class ServerClass < EventMachine::Connection
  def initialize(*args)
    # ruby singleton - store channel data in global hash
    ($channels ||= [])
  end

  def post_init
    puts "initialized"
    $cb.call("initialized");
  end

  def receive_data(data)
    # got information from client connection
  end

  def channel_send(msg,channel)
    $channels[channel].send_data(msg)
  end

  def channels_send(msg)
    $channels.each{|channel| channel.send_data(msg)}
  end

  def unbind
    # puts user left
  end

end

EventMachine.run do
  $cb = EM.callback {|msg| puts msg #do something creative}
  $ems = EventMachine::start_server('0.0.0.0',ServerClass,args)

  class App < Sinatra::Base
    set :public, File.dirname(__FILE__) + '/public'

    get '/' do
      erb :index          
    end

  end

  App.run!({:port => 3000})

end

上面是一个基本的线框。根据您希望如何发送数据,您可以使用 WebSockets (em-websocket) 并在登录时绑定每个用户(必须添加登录系统),或者您可以将其用于任何用途。只要您拥有对 Eventmachine 对象(连接、websocket、通道)的全局引用,您就可以从应用程序中传递消息。

顺便说一句 - 添加 EventMachine.run do;....end 循环是可选的,因为 Thin 无论如何都会这样做。它有助于了解它是如何工作的。

祝你好运

于 2011-08-10T22:44:04.787 回答