我遇到以下问题,对于拥有更多知识或经验的人来说,这可能是直截了当的。花了整个周末试图找出它没有成功......非常感谢额外的帮助和见解,谢谢。
我有一个类变量@@clients
,用于跟踪打开的websocket连接。当我从on.message
块(在新线程中)的redis_sub.subscribe
块内访问该变量时,该数组为空。我创建了一个测试类变量@@test
,每次发生新的websocket连接时都会递增,并记录该变量,同样,日志显示@@test
为0,即其初始值。
class Shrimp
# Heroku has a 50 seconds idle connection time limit.
KEEPALIVE_TIME = 15 # in seconds
@@clients = []
@@test = 0
class << self
def load_session(client)
if !client.env["rack.session"].loaded?
client.env["rack.session"][:init] = true
end
end
def get_client(user_id)
# check if user is one of the ws clients
@@clients.each do |client|
# lazily load session
load_session(client)
# get user_id from the session
if(client.env["rack.session"]["warden.user.user.key"][0][0] == user_id)
return client
end
end
nil
end
end
def initialize(app)
@app = app
redis_uri = URI.parse(ENV["REDISCLOUD_URL"])
# work on a separte thread not to block current thread
Thread.new do
redis_sub = Redis.new(host: redis_uri.host, port: redis_uri.port, password: redis_uri.password)
redis_sub.subscribe(ENV["REDIS_CHANNEL"]) do |on| # thread blocking operation
p [:redis_suscribe]
p [:test, @@test]
on.message do |channel, msg|
data = JSON.parse(msg)
p [:redis_receive_message, data]
p [:test, @@test]
client = Shrimp.get_client(data["user_id"])
client.send(data["thumbnail_urls"].to_json) if client
end
end
end
end
def call(env)
env['rack.shrimp'] = self
if Faye::WebSocket.websocket?(env)
puts websocket_string
# Send every KEEPALIVE_TIME sec a ping for keeping the connection open.
ws = Faye::WebSocket.new(env, nil, { ping: KEEPALIVE_TIME })
ws.on :open do |event|
puts '***** WS OPEN *****'
@@clients << ws
@@test = @@test + 1
p [:test, @@test]
end
ws.on :message do |event|
puts '***** WS INCOMING MESSAGE *****'
p [:message, event.data]
p [:test, @@test]
@@clients.each { |client| client.send(event.data.to_json) }
end
ws.on :close do |event|
puts '***** WS CLOSE *****'
p [:close, ws.object_id, event.code, event.reason]
@@clients.delete(ws)
p [:test, @@test]
ws = nil
end
ws.on :error do |event|
puts '***** WS ERROR *****'
p [:close, ws.object_id, event.code, event.reason]
end
# Return async Rack response
ws.rack_response
else
@app.call(env)
end
end
end
我们可以在第一个连接打开后看到@@test
类变量为1
,当服务器从该客户端收到消息时仍然1
,当记录时0
当关闭websocket连接时,从on.message
块内再次1
。
我显然遗漏了一些东西,但是尽管进行了所有的研究和阅读,却无法弄明白。