简体   繁体   English

如何使用sinatra流式api关闭redis连接?

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

I have the following sinatra app: 我有以下sinatra应用程序:

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. 基本上,它使用redis pubsub接收其他用户发布到feed的事件,然后使用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. 问题是,当浏览器重新连接到源时,redis客户端保持连接,并且它一直接收事件,因此redis服务器充满了无用的连接。 how can i close all this connections once the broser closes the connection to the web server? 一旦broser关闭与Web服务器的连接,我该如何关闭所有这些连接?

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): 经过大量的研究和实验,这里是我与sinatra + sinatra sse gem使用的代码(应该很容易适应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. redis连接阻止on.message并且只接受(p)subscribe /(p)unsubscribe命令。 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. 取消订阅后,redis连接不再被阻止,并且可以由初始sse请求实例化的Web服务器对象释放。 It automatically clears when you receive a message on redis and sse connection to the browser no longer exists in the collection array. 当您在redis上收到消息时,它会自动清除,并且集合数组中不再存在与浏览器的连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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