是否可以从Thin / Rack / Sinatra访问Ruby EventMachine频道?

时间:2011-04-22 14:48:52

标签: ruby sinatra rack eventmachine thin

我正在寻求为利用Sinatra的内部项目构建一个简单的RESTful通知系统。我过去曾使用EventMachine频道订阅/发布事件,但在以前的所有情况下,我都是直接使用EventMachine。

有没有人知道是否有可能从Sinatra应用程序创建,订阅和发布到EventMachine通道(以Thin运行),甚至可能从某些Rack中间件发布到该事件?

2 个答案:

答案 0 :(得分:2)

查看async_sinatra

基本上,为了能够在Thin中运行时使用EventMachine,您需要让它知道您想要异步地提供请求。 Rack协议在设计上是同步的,Thin期望在处理程序返回时完成请求。有一些方法可以让Thin意识到您想要异步处理请求(请参阅think_async了解示例),async_sinatra使其变得非常简单。

答案 1 :(得分:1)

布莱恩 您可以使用em-http-request库(https://github.com/igrigorik/em-http-request),这将允许您引用在A.同一服务器上运行的特定EventMachine应用程序,B。不同的服务器,或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,通道)的全局引用,您就可以从应用程序中传递消息。

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

祝你好运