我正在使用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