2013-05-22 6 views
6

私は(redis)pub/subサブスクライバも追加する必要があるRails(web)アプリケーションを持っています。Railsアプリケーションでpubsubサブスクライバを起動する方法

以下は、PubsubSubscriberクラスです。これは、アプリの起動に必要なものです。

redis接続は、resque.rb初期化ファイルに作成されます。私は、接続後PubsubSubscriber.newを試してみましたが、私はでそれがハングレールのサーバを起動しようとすると:サーバーが正常に起動したときとは対照的に

=> Booting Thin 
=> Rails 3.2.13 application starting in development on http://0.0.0.0:5000 
=> Call with -d to detach 
=> Ctrl-C to shutdown server 

=> Booting Thin 
=> Rails 3.2.13 application starting in development on http://0.0.0.0:5000 
=> Call with -d to detach 
=> Ctrl-C to shutdown server 
>> Thin web server (v1.5.1 codename Straight Razor) 
>> Maximum connections set to 1024 
>> Listening on 0.0.0.0:5000, CTRL+C to stop 

任意のアイデアなぜサーバーイニシャライザでPubsubSubscriberクラスのインスタンスを作成しようとするとハングしますか?これを始めるのに良い場所はありますか?あなたが持っている


# example modified from https://github.com/redis/redis-rb/blob/master/examples/pubsub.rb 
class PubsubSubscriber 

    def initialize 
    $redis.psubscribe(:channel_one) do |on| 

     on.psubscribe do |event, total| 
     end 

     on.pmessage do |pattern, event, message| 
     # message received, kick off some workers 
     end 

     on.punsubscribe do |event, total| 
     end 

    end 

end 
end 
+0

thats通常、subscribeコールは '永遠に'ブロックします。イベントマシンや別のプロセス/スレッドで実行する必要があります –

+0

私はThinを使用しています。ハンドルはEMのものと同じように聞こえるので、EM.runを明示的に呼び出す必要はありません。私はThread.new {PubsubSubscriber.new}を試しましたが、それもブロックしています。提案? – 99miles

+0

オブジェクトのコンストラクタは、ブロッキングイベントを実行する場所ではなく、実行中のクエリなどの何かを実行する場所ではありません。これは、オブジェクトの初期化にのみ使用する必要があります。 Ruby Objectシステムが、オブジェクトが正しく作成されるためにコンストラクタが終了するのを待っているなら、私は驚くことはありません。ですから、これをコンストラクタの外で 'start'のような別のメソッドに移動し、' Thread.new {PubsubSubscriber.new.start} 'のように実行してみてください。 – Subhas

答えて

4

一つの問題は、あなたが初期化しているときEventMachineはまだ準備ができていないということです。だから、EventMachineの準備ができるまで、あなたのコードを遅らせますEM.next_tickであなたの初期化をラップ:

EM.next_tick { ... EventMachine code here ... } 

私はこれを試したときは、私のサーバーはすべての方法を起動...と$への呼び出しが発射さredis.psubscribeときにブロックされました。

はしかし、em-hiredisへの切り替えが働いた:標準Redisの宝石がEventMachineインタフェースを介してイベントをリスニングされていないため、

# config/initializers/redis_pubsub.rb 
EM.next_tick do 
    $emredis = EM::Hiredis.connect(uri) 

    $emredis.pubsub.subscribe('channelone') do |message| 
    Rails.logger.debug message 
    end 
end 

これが起こっている - それはちょうどあなたのRedisのサーバーへの接続を作成してから、すべてをブロックしていますelse。

あなたがの形で、簡単な接続をセットアップする必要がありますEMを利用するためには:

class RedisConnection 
    # connect to redis 
    def connect(host, port) 
     EventMachine.connect host, port, self 
    end 

    def post_init 
     # send subscribe channel_one to redis  
    end 

    def receive_data(data) 
     # channel_one messages will arrive here 
    end 
end 

私はこの趣旨での作業例を持っている:https://gist.github.com/wheeyls/5647713

em-hiredisこのインタフェースを使用するRedisクライアントです。

関連する問題