2011-04-22 57 views
2

我期待爲利用Sinatra的內部項目構建一個簡單的RESTful通知系統。過去我使用過EventMachine頻道來訂閱/發佈事件,但在我以前的所有情況下,我都是直接使用EventMachine。是否可以從Thin/Rack/Sinatra訪問Ruby EventMachine頻道?

是否有人知道是否可以從Sinatra應用程序創建,訂閱併發布到EventMachine渠道(以Thin方式運行),或者甚至可以從某些Rack中間件那裏發佈?

回答

2

看看async_sinatra

基本上,爲了在Thin中運行時使用EventMachine成爲可能,您需要讓它知道您想異步地處理請求。 Rack協議在設計上是同步的,而Thin期望在處理程序返回時執行請求。有很多方法可以讓Thin知道您想異步處理請求(有關示例,請參閱think_async),並且async_sinatra使其變得非常簡單。

+0

嗯...所以我不需要異步儘可能多的服務請求,我只是需要一種方法來利用EventMachine的的通道對象。但是,您的回答使我明白,以Thin方式運行的EventMachine僅適用於Rack應用程序,只需通過引用EM就可以實現。 因此,你已經回答了我的問題。感謝Theo! – Bryan 2011-04-22 19:09:48

+0

我以爲你想在你的應用程序中使用頻道進行通信。例如,在處理您想要發佈到頻道的請求時,等待另一個頻道的回覆,或者您想要彈出一個隊列。這些是異步操作,並且您必須異步處理請求以處理它們。例如,如果你運行'queue.pop {| msg | ...}您的請求在調用回調/塊時已經發送。 – Theo 2011-04-22 19:39:07

+0

是的,我沒有必要解釋我想要完成什麼。本質上,我想提供一個RESTful界面來創建,推送和註冊頻道,以支持在我的應用程序之外通知其他Web服務器。最後,我希望一個客戶端能夠將通知推送到一個通道,並通過在queue.pop塊中定義的單獨HTTP請求通知所有註冊了所述通道的Web服務器。 – Bryan 2011-04-22 19:51:06

1

Bryan, 您可以使用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 

上面是一個基本的線框。根據你想要發送數據的方式,你可以使用WebSocket(em-websocket)並在登錄時綁定每個用戶(必須添加一個登錄系統),或者你可以使用它來做任何事情。只要您有對Eventmachine對象(連接,websocket,通道)的全局引用,就可以傳遞應用程序內的消息。

順便說一句 - 添加EventMachine.run do; .... end循環是可選的,因爲Thin會做到這一點。它有助於瞭解它是如何工作的。

好運