2013-01-10 14 views
17

Ich versuche Text/Event-Stream mit Rails 4 Live Streaming zu implementieren. Es funktioniert gut und das einzige Problem, das ich traf, ist, dass ich nicht überprüfen kann, ob die Verbindung aktiv ist, ohne irgendwelche Nachrichten zu senden.ActionController :: LIve Ist es möglich zu überprüfen, ob die Verbindung noch besteht?

Die einzige Lösung, die ich herausgefunden habe, ist, einen unterstützenden Kanal mit einem zyklischen Tick-Generator zu erzeugen, so dass einige Hintergrund-Tasks Nachrichten dort periodisch senden werden. Aber es scheint chaotisch und nicht zuverlässig zu sein. Irgendwelche besseren Lösungen?

Hier ist mein Controller:

require 'persistency/sse' 
require 'persistency/track' 

class PersistencyController < ApplicationController 
    include ActionController::Live 

    def stream 
    response.headers['Content-Type'] = 'text/event-stream' 

    sse = Persistency::SSE.new(response.stream) 
    track = Persistency::Track.new(current_user) 
    redis = Redis.new 

    begin 
     redis.subscribe(:info, :chat) do |on| 
     on.message do |channel, message| 
      sse.write({ :message => message }, :event => channel) 
     end 
     end 
    rescue IOError 
    ensure 
     track.close 
     sse.close 
    end 
    end 
end 
+0

Eine weitere Option hier detailliert: http://StackOverflow.com/a/19485363/928963 –

+0

Sieht aus wie genau das gleiche wie unten gezeigt, außer dass es Redis für die Ausgabe von Taktsignal verwendet, die komplexer ist. Und wie funktioniert es unter Last? Initialisiert der Initializer nicht bei jeder Anfrage? Dies kann den Pub/Sub-Kanal überlasten und jeder Client erhält Nachrichten von allen Clients. –

+0

Die Lösung, die Sie unten haben, feuert einen zusätzlichen Ticker-Thread pro Clientverbindung ab. Die Lösung, die ich in meiner Antwort, auf die ich Bezug genommen habe, vorgeschlagen habe, hat einen einzelnen Thread, um diese Ticker herauszuschieben, der etwas besser skaliert. (Und das Einfügen in den Initialisierer erzeugt einen Thread pro Rails-Prozess, nicht pro Client-Verbindung) –

Antwort

10

Ok, fand ich zwei Möglichkeiten:

1) Lustig, aber nicht gut (wie ich nicht bekommen, was Sever soll ich 1000 von parallel zu handhaben verwenden Verbindungen):

begin 
    ticker = Thread.new { loop { sse.write 0; sleep 5 } } 
    sender = Thread.new do 
    redis.subscribe(:info, :chat) do |on| 
     on.message do |event, message| 
     sse.write(message, :event => event.to_s) 
     end 
    end 
    end 
    ticker.join 
    sender.join 
rescue IOError 
ensure 
    Thread.kill(ticker) if ticker 
    Thread.kill(sender) if sender 
    track.close 
    sse.close 
end 

2) Super. Um Goliath Server zu benutzen. Es stellte sich heraus, dass es überprüfen kann, ob die Verbindung ohne Ticker verloren gegangen ist. Auf dem Weg nach Goliath fand Cramp. Es ist leicht und hoffentlich schnell, scheint aber aufgegeben zu sein.