rails全局变量在线程中不可访问

时间:2016-07-21 18:19:02

标签: ruby-on-rails multithreading redis faye

我正在使用Faye websockets和Redis为幻灯片演示文稿尝试主/客户端websocket设置。 客户应该全部跟随主人(即主人向前移动幻灯片,向所有客户发送消息,他们都向前移动幻灯片)。

我遇到的问题是当我访问初始化函数中创建的线程内部时,我的客户端websockets列表为空。单独的线程是必要的,因为Redis''subscribe'是一个阻塞函数。 这个文件是一个中间件,可以在app启动时运行。

我知道rails中全局变量的 point 是它们在线程之间共享,但在我的情况下似乎有些东西阻止了它。

有没有办法在全球可访问的地方存储一个websockets列表?全局,如同在同一服务器上的所有正在运行的应用程序实例一样。 (不能使用Redis,因为它无法存储对象)。

require 'faye/websocket'
require 'redis'

class WsCommunication
  KEEPALIVE_TIME = 15 #seconds
  CHANNEL = 'vip'

def initialize(app)
@app = app
$clients = []

uri = URI.parse(ENV['REDISCLOUD_URL'])
Thread.new do
  redis_sub = Redis.new(host: uri.host, port: uri.port, password: uri.password)
  redis_sub.subscribe(CHANNEL) do |on|
    on.message do |channel, msg|
      puts 'client list on thread'
      puts $clients
      #### prints nothing
      $clients.each { |ws| ws.send(msg) }
    end
  end
end
end

def call(env)
if Faye::WebSocket.websocket?(env)
  ws = Faye::WebSocket.new(env, nil, {ping: KEEPALIVE_TIME})
  ws.on :open do |event|
    $clients << ws
  end

  ws.on :message do |event|
    puts 'client list'
    puts $clients
    ### prints the full list of clients
    $redis.publish(CHANNEL, event.data)
  end

  ws.on :close do |event|
    $clients.delete(ws)
    ws = nil
  end

  # Return async Rack response
  ws.rack_response
else
  @app.call(env)
end
end

end

0 个答案:

没有答案