我正在寻求为利用Sinatra的内部项目构建一个简单的RESTful通知系统。我过去曾使用EventMachine频道订阅/发布事件,但在以前的所有情况下,我都是直接使用EventMachine。
有没有人知道是否有可能从Sinatra应用程序创建,订阅和发布到EventMachine通道(以Thin运行),甚至可能从某些Rack中间件发布到该事件?
答案 0 :(得分:2)
基本上,为了能够在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无论如何都会这样做。它有助于了解它的工作原理。
祝你好运