简体   繁体   中英

how do I close a redis connection using the sinatra streaming api?

I have the following sinatra app:

require 'sinatra'
require 'redis'
require 'json'


class FeedStream < Sinatra::Application


  helpers do
    include SessionsHelper

    def redis
      @redis ||= Redis.connect
    end
  end

  get '/feed', provides: 'text/event-stream' do


    stream do |out|

      redis.subscribe "feed" do |on|

        on.message do |channel, message|
          event_data = JSON.parse message
          logger.info "received event = #{event_data}"
          out << "event: #{event_data['event']}\n"
          out << "data: #{{:data => event_data['data'],
                           :by => current_user}}.to_json\n\n"
        end
      end
    end

  end

end

basically, it receives events published by other users to a feed using redis pubsub, and then it sends those events with the sinatra streaming api. The problem is that, when the browser reconnects to the feed, the redis client keeps connected, and it keeps receiving events, so the redis server gets full of useless connections. how can i close all this connections once the broser closes the connection to the web server?

I know it's been a while.

Were you looking for quit ?

After much research and experimentation, here's the code I'm using with sinatra + sinatra sse gem (which should be easily adapted to Rails 4):

class EventServer < Sinatra::Base
 include Sinatra::SSE
 set :connections, []
 .
 .
 .
 get '/channel/:channel' do
 .
 .
 .
  sse_stream do |out|
    settings.connections << out
    out.callback {
      puts 'Client disconnected from sse';
      settings.connections.delete(out);
    }
  redis.subscribe(channel) do |on|
      on.subscribe do |channel, subscriptions|
        puts "Subscribed to redis ##{channel}\n"
      end
      on.message do |channel, message|
        puts "Message from redis ##{channel}: #{message}\n"
        message = JSON.parse(message)
        .
        .
        .
        if settings.connections.include?(out)
          out.push(message)
        else
          puts 'closing orphaned redis connection'
          redis.unsubscribe
        end
      end
    end
  end
end

The redis connection blocks on.message and only accepts (p)subscribe/(p)unsubscribe commands. Once you unsubscribe, the redis connection is no longer blocked and can be released by the web server object which was instantiated by the initial sse request. It automatically clears when you receive a message on redis and sse connection to the browser no longer exists in the collection array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM