lua-resty-redis icon indicating copy to clipboard operation
lua-resty-redis copied to clipboard

calling read_reply in a while true loop gets timeout error

Open xiangnanscu opened this issue 5 years ago • 1 comments
trafficstars

Hello, this code I get from some blog explaining a simple chatroom code. Function heros is called when a websocket connects the openresty.All fine except regular timeout error happens about once per second when calling red:read_reply . While red:read_reply can return normal message.

I just wondering why timeout error happens. is this normal?

local function heros(request)
  local server = require "resty.websocket.server"
  local redis = require "resty.redis"
  local encode = require "cjson.safe".encode
  local decode = require "cjson.safe".decode
  local channel_name = "heros"


  local wb, err = server:new{
    timeout = 10000,
    max_payload_len = 65535
  }

  -- sub thread listening redis server and send to the websocket client
  local function push()
    local red = redis:new()
    red:set_timeout(6000) 
    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
      return
    end

    local res, err = red:subscribe(channel_name)
    if not res then
      red:close()
      return
    end

    while true do
      local res, err = red:read_reply()
      if res then
        local bytes, err = wb:send_text(res[3])
        if not bytes then
          break
        else
        end
      else
        -- here, regular timeout error happens, about 1 per second
        loger('REDIS read_reply err:'..err)
      end
    end
    red:set_keepalive(10000, 100)
  end

  -- open this thread to publish message to clients
  local co = ngx.thread.spawn(push)

  -- main thread, listening clients' websocket message
  while true do
    if wb.fatal then
      break
    end

    local data, typ, err = wb:recv_frame()

    if not data then
      local bytes, err = wb:send_ping()
      if not bytes then
        break
      end
    elseif typ == "text" then
      local red2 = redis:new()
      red2:set_timeout(1000) 
      local ok, err = red2:connect("127.0.0.1", 6379)
      if not ok then
      else
        -- publish data directly
        local res, err = red2:publish(channel_name, data)
        if not res then
          red2:close()
        else
          red2:set_keepalive(10000, 100)
        end
      end
    elseif typ == "close" then
      break
    elseif typ == "ping" then
      local bytes, err = wb:send_pong()
      if not bytes then
        break
      end
    elseif typ == "pong" then
    else 
    end
  end
  wb:send_close()
  ngx.thread.wait(co)
end

return heros

xiangnanscu avatar Jul 18 '20 06:07 xiangnanscu

Note, calling the red:read_reply can get correct message after this message is published.

xiangnanscu avatar Jul 18 '20 06:07 xiangnanscu