Sinatra で WebSocket のような stream の簡便な実装を書くことができます.
簡易なチャットシステムや,流れてくるログ拾ってきてブラウザで眺めるなどの用途に使えそうです.
get '/', provides: 'text/event-stream' do
stream :keep_open do |conn|
conn << 'なにがしかの処理'
sleep 1
end
end
loop したい
たとえば,ログを眺めるような用途だと,ログを監視して差分を送ってあげるなどの処理が必要になるでしょう.
loop ブロックを使用したくなることがありそうです.
stream :keep_open do |conn|
loop do
conn << 'データの差分を送る'
sleep 1
end
end
しかし,この実装だと,ブラウザをリロードしてみると以前のコネクションが残ってしまいます.
次のようにしてサーバログを見ると,リロードした数だけ余分に呼ばれていることがわかります.
stream :keep_open do |conn|
loop do
p 'loop'
conn << 'データの差分を送る'
sleep 1
end
end
connection が切れたことを検知するには,callback を利用するのが良さそうです.
stream :keep_open do |conn|
loop do
conn << 'データの差分を送る'
conn.errback { p 'closed' }
sleep 1
end
end
ただし,callback の Proc 内では loop ブロックを break できないので,次のようにしてコネクションを管理することにします.
get '/', provides: 'text/event-stream' do
conns = []
stream :keep_open do |conn|
conns << conn
loop do
conn << 'データの差分を送る'
# if connection closed
conn.callback { conns.delete conn }
conn.errback { conns.delete conn }
break unless conns.include? conn
sleep 1
end
end
end