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

发布于 2024-11-02 18:12:30 字数 193 浏览 5 评论 0原文

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

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

I'm looking to build a simple, RESTful notification system for an internal project leveraging Sinatra. I've used EventMachine channels in the past to subscribe/publish to events, but in all my previous cases I was using EventMachine directly.

Does anyone know if it's possible to create, subscribe, and publish to EventMachine channels (running in Thin) from a Sinatra application, or even from some Rack middleware for that matter?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

断爱 2024-11-09 18:12:30

看看async_sinatra

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

Have a look at async_sinatra.

Basically, to make it possible to use EventMachine when running in Thin you need to make it aware that you want to serve requests asynchronously. The Rack protocol is synchronous by design, and Thin expects a request to be done when the handler returns. There are ways to make Thin aware that you want to handle the request asynchronously (see think_async for an example how), and async_sinatra makes it very easy.

じ违心 2024-11-09 18:12:30

布莱恩,
您可以使用 em-http-request 库 (https://github.com/igrigorik/em-http-request),这将允许您引用在 A. 同一服务器、B. a 上运行的特定 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 无论如何都会执行此操作。了解它是如何工作的还是有帮助的。

祝你好运

Bryan,
You can use the em-http-request library (https://github.com/igrigorik/em-http-request), this will allow you to reference a specific EventMachine application running on either A. the same server, B. a different server, or C. wherever you want really.

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

Above is a basic wireframe. Depending on how you want to go about sending data, you can use WebSockets (em-websocket) and bind each user on login (have to add a login system), or you can use this for whatever. As long as you have a global reference to the Eventmachine Object (connection, websocket, channel) you can pass messages from within your application.

BTW - It is optional to add the EventMachine.run do;....end loop, since Thin will do this anyways. It helps to know how it works though.

Good Luck

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文