我希望为利用 Sinatra 的内部项目构建一个简单的 RESTful 通知系统。我过去曾使用 EventMachine 频道来订阅/发布事件,但在我之前的所有案例中,我都直接使用 EventMachine。
有谁知道是否可以从 Sinatra 应用程序或什至从某些 Rack 中间件创建、订阅和发布到 EventMachine 通道(在 Thin 中运行)?
我希望为利用 Sinatra 的内部项目构建一个简单的 RESTful 通知系统。我过去曾使用 EventMachine 频道来订阅/发布事件,但在我之前的所有案例中,我都直接使用 EventMachine。
有谁知道是否可以从 Sinatra 应用程序或什至从某些 Rack 中间件创建、订阅和发布到 EventMachine 通道(在 Thin 中运行)?
基本上,要在 Thin 中运行时使用 EventMachine,您需要让它知道您想要异步处理请求。Rack 协议在设计上是同步的,Thin 期望在处理程序返回时完成请求。有一些方法可以让 Thin 意识到您想要异步处理请求(有关如何处理的示例,请参见think_async ),而async_sinatra使这变得非常容易。
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 无论如何都会这样做。它有助于了解它是如何工作的。
祝你好运