我正在使用websockets,redis和threads进行基本的聊天设置。我在线程启动之前创建一个客户端数组,然后更新客户端数组。但是,线程中永远不会更新客户端数组。因此,当我尝试发布到连接的客户端时,没有发布任何内容。我正在处理example directly on Heroku并且无法弄清楚客户端数组没有更新的原因。
这是我的代码:
class ChatBackend
KEEPALIVE_TIME = 15 # in seconds
CHANNEL = "chat-demo"
def initialize(app)
@app = app
@clients = []
uri = URI.parse(ENV["REDISCLOUD_URL"])
@redis = Redis.new(host: uri.host, port: uri.port, password: uri.password)
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|
# @clients never gets updated, always stays empty
@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|
@redis.publish(CHANNEL, prepare(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
private
def prepare(data)
json = JSON.parse(message)
json.each {|key, value| json[key] = ERB::Util.html_escape(value) }
JSON.generate(json)
end
end
答案 0 :(得分:0)
这花了我一整天的时间来确定,但它包含在Heroku示例here的wiki问题中:
指定工作人员将puma置于聚集模式,并稍微打破了我 本例中提供的中间件的修改版本。
我确认消息正在正确发布到redis pubsub通道,以及线程内部的redis订阅 确实收到消息并触发on.message块,但是ws 浏览器中的客户端永远不会收到消息。
这是因为@clients在线程内是一个空数组(对于a 这是逃避我的原因),意味着该块传递给了 永远不会执行@ clients.each,因此消息就会消失。
在该线程之外访问@clients会返回所有打开的内容 ws连接正确。
删除worker 3行修复了这个问题,但我想我会这样做 报告它,以防其他人自己碰到这个。