2013-05-22 14 views
6

starten Ich habe eine Rails (Web) -App, die ich hinzufügen muss auch einen (Redis) Pub/Sub-Abonnenten.Wie Kickstub Subscriber in Rails app

Unten ist meine Pubsubsubscriber-Klasse, die ich starten muss, dann startet die App.

Die Redis-Verbindung wird in einer Initialisierungsdatei resque.rb erstellt. Ich habe versucht, PubsubSubscriber.new nach der Verbindung, aber wenn ich versuche, den Schienen-Server zu starten es hängt: im Gegensatz zu

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

wenn der Server startet erfolgreich:

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

Jede Idee, warum der Server hängt, wenn ich versuche, die Pubsubsubscriber-Klasse im Initialisierer zu instanziieren? Gibt es einen besseren Ort, um damit anzufangen?


# 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

das ist normal, der abonnierte Anruf blockiert "für immer"; Sie sollten das mit etwas wie eventmachine oder in einem anderen Prozess/Thread –

+0

Ich verwende Thin, die es klingt wie Griff ist die EM-Zeug für mich, so dass ich nicht explizit EM.run Anrufe brauchen. Ich habe versucht Thread.new {PubsubSubscriber.new}, aber das blockiert auch. Vorschläge? – 99miles

+0

Der Konstruktor eines Objekts ist ** nicht ** der Ort, an dem Ereignisse blockiert werden, oder sogar irgendetwas anderes, wie das Ausführen von Abfragen oder Ähnlichem. Es sollte nur verwendet werden, um ein Objekt zu initialisieren. Ich wäre nicht überrascht, wenn das Ruby-Objekt-System auf den Abschluss des Konstruktors wartet, damit das Objekt ordnungsgemäß erstellt wird. Versuchen Sie also, dies außerhalb eines Konstruktors in eine separate Methode wie 'start' zu verschieben und führen Sie sie wie' Thread.new {PubsubSubscriber.new.start} 'aus – Subhas

Antwort

4

Ein Problem, das Sie haben, ist, dass eventmachine noch nicht bereit ist, wenn Sie in den Initialisierer sind. So Ihre Initialisierung in EM.next_tick Verpackung wird Ihr Code verzögern, bis eventmachine bereit ist:

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

Als ich das versucht, meine Server in Betrieb genommen den ganzen Weg ... und dann blockiert, wenn der Anruf zu $ ​​gefeuert redis.psubscribe.

jedoch zu em-hiredis Schalt gearbeitet:

# 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 

Dies geschieht, weil das Standard redis Juwel nicht für Veranstaltungen durch die eventmachine Schnittstelle hören - es ist nur eine Verbindung zu Ihrem redis Server erstellen und dann alles blockiert sonst.

Um die Vorteile von EM nutzen, um Ihnen eine einfache Verbindung einrichten müssten, in Form von:

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 

Ich habe ein funktionierendes Beispiel in diesem Kern bekam: https://gist.github.com/wheeyls/5647713

em-hiredis ist ein Redis-Client, der diese Schnittstelle verwendet.

Verwandte Themen