2013-05-22 12 views
6

Mam aplikację Rails (sieć), która jest potrzebna do dodania subskrybenta (redis) pub/sub.Jak uruchomić subskrybenta subskrypcji programu pubsub w aplikacji Railsowej

Poniżej znajduje się moja klasa PubsubSubscriber, którą muszę uruchomić, a następnie uruchamia się aplikacja.

Połączenie redis jest tworzone w pliku inicjalizacyjnym resque.rb. Próbowałem PubsubSubscriber.new po połączeniu, ale gdy próbuję uruchomić serwer szyn wisi na:

=> 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 

w przeciwieństwie do tego, kiedy serwer zacznie skutecznie:

=> 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 

Każdy pomysł dlaczego serwer zawiesza się, gdy próbuję utworzyć instancję klasy PubsubSubscriber w inicjatorze? Czy jest lepsze miejsce na rozpoczęcie tego?


# 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

To normalne, subskrypcja blokuje "na zawsze"; powinieneś uruchomić to z czymś takim jak eventmachine lub innym procesem/wątkiem –

+0

Używam Thin, co brzmi jak handle dla EM, więc nie potrzebuję wyraźnych wywołań EM.run. Próbowałem Thread.new {PubsubSubscriber.new}, ale to też się blokuje. Propozycje? – 99miles

+0

Konstruktor obiektu ** nie ** jest miejscem wykonywania blokowania zdarzeń, a nawet wykonywania innych czynności, takich jak uruchamianie zapytań lub innych. Powinien być używany tylko do zainicjowania obiektu. Nie zdziwiłbym się, gdyby system obiektów Ruby czekał na zakończenie konstruktora, aby obiekt został poprawnie utworzony. Więc spróbuj przenieść to poza konstruktorem i do oddzielnej metody, takiej jak 'start', i uruchom ją jak' Thread.new {PubsubSubscriber.new.start} – Subhas

Odpowiedz

4

Jeden problem, że masz to, że EventMachine nie jest jeszcze gotowy, gdy jesteś w inicjatora. Więc owijając swoją inicjację w EM.next_tick opóźni swój kod aż EventMachine jest gotowe:

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

Kiedy próbowałem to mój serwer uruchomiony przez całą drogę ... a potem zablokowany, gdy wezwanie do $ redis.psubscribe zwolniony.

Jednak przejście na em-hiredis pracował:

# 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 

Dzieje się tak dlatego, że klejnot standardowe Redis nie nasłuchuje zdarzeń poprzez interfejs EventMachine - to jest po prostu tworząc połączenie z serwerem Redis, a następnie blokuje wszystko jeszcze.

W celu skorzystania z EM trzeba byłoby założyć prostego połączenia, w formie:

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 

Mam przykład pracujących w tym GIST: https://gist.github.com/wheeyls/5647713

em-hiredis jest klientem redis, który używa tego interfejsu.

Powiązane problemy