mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 20:23:06 +00:00
redesign connection module
This commit is contained in:
@@ -1,34 +1,31 @@
|
||||
local skynet = require "skynet"
|
||||
local socket = require "socket"
|
||||
local string = string
|
||||
local table = table
|
||||
local tonumber = tonumber
|
||||
local ipairs = ipairs
|
||||
local unpack = unpack
|
||||
local redis_server = ...
|
||||
local fd
|
||||
local write_fd
|
||||
local readline_fd
|
||||
local read_fd
|
||||
local close_fd
|
||||
|
||||
local function init_fd(fdstr)
|
||||
fd = fdstr
|
||||
write_fd = "WRITE "..fd.." "
|
||||
readline_fd = "READLINE ".. fd .." \r\n"
|
||||
read_fd = "READ " .. fd .. " "
|
||||
close_fd = "CLOSE "..fd
|
||||
end
|
||||
|
||||
local function init()
|
||||
fd = skynet.call(".connection", "CONNECT " .. redis_server)
|
||||
if fd == nil then
|
||||
print("Connect to redis server error : ", redis_server)
|
||||
skynet.exit()
|
||||
return true
|
||||
local function read(bytes)
|
||||
while true do
|
||||
local result = socket.read(bytes)
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
coroutine.yield()
|
||||
end
|
||||
init_fd(fd)
|
||||
end
|
||||
|
||||
local function readline(sep)
|
||||
while true do
|
||||
local result = socket.readline(sep)
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
|
||||
local function compose_message(msg)
|
||||
local lines = { "*" .. #msg }
|
||||
@@ -42,72 +39,109 @@ local function compose_message(msg)
|
||||
return cmd
|
||||
end
|
||||
|
||||
local function init()
|
||||
socket.connect(redis_server)
|
||||
end
|
||||
|
||||
local request_queue = { head = 1, tail = 1 }
|
||||
|
||||
local function push_request_queue(reply)
|
||||
request_queue[request_queue.tail] = reply
|
||||
request_queue.tail = request_queue.tail + 1
|
||||
end
|
||||
|
||||
local function pop_request_queue()
|
||||
assert(request_queue.head < request_queue.tail)
|
||||
local reply = request_queue[request_queue.head]
|
||||
request_queue[request_queue.head] = nil
|
||||
request_queue.head = request_queue.head + 1
|
||||
return reply
|
||||
end
|
||||
|
||||
local function response(...)
|
||||
local reply = pop_request_queue()
|
||||
skynet.send(reply[2],reply[1],skynet.pack(...))
|
||||
end
|
||||
|
||||
local redcmd = {}
|
||||
|
||||
redcmd[42] = function(data) -- '*'
|
||||
local n = tonumber(data)
|
||||
if n < 1 then
|
||||
skynet.ret(skynet.pack(true, nil))
|
||||
response(true, nil)
|
||||
return
|
||||
end
|
||||
local bulk = {}
|
||||
for i = 1,n do
|
||||
local line = skynet.call(".connection", readline_fd)
|
||||
local line = socket.readline "\r\n"
|
||||
if line == nil then
|
||||
return "BLOCK"
|
||||
end
|
||||
local bytes = tonumber(string.sub(line,2) + 2)
|
||||
local data = skynet.call(".connection", read_fd .. bytes)
|
||||
local data = socket.read(bytes)
|
||||
if data == nil then
|
||||
return "BLOCK"
|
||||
end
|
||||
table.insert(bulk, string.sub(data,1,-3))
|
||||
end
|
||||
skynet.ret(skynet.pack(true,bulk))
|
||||
response(true, bulk)
|
||||
end
|
||||
|
||||
redcmd[36] = function(data) -- '$'
|
||||
local bytes = tonumber(data)
|
||||
if bytes < 0 then
|
||||
skynet.ret(skynet.pack(true, nil))
|
||||
response(true,nil)
|
||||
return
|
||||
end
|
||||
local firstline = skynet.call(".connection", read_fd .. (bytes + 2))
|
||||
skynet.ret(skynet.pack(true,string.sub(firstline,1,-3)))
|
||||
local firstline = socket.read(bytes+2)
|
||||
if firstline == nil then
|
||||
return "BLOCK"
|
||||
end
|
||||
response(true,string.sub(firstline,1,-3))
|
||||
end
|
||||
|
||||
redcmd[43] = function(data) -- '+'
|
||||
skynet.ret(skynet.pack(true, data))
|
||||
response(true,data)
|
||||
end
|
||||
|
||||
redcmd[45] = function(data) -- '-'
|
||||
skynet.ret(skynet.pack(false, data))
|
||||
response(false,data)
|
||||
end
|
||||
|
||||
redcmd[58] = function(data) -- ':'
|
||||
skynet.ret(skynet.pack(true, tonumber(data)))
|
||||
response(true, tonumber(data))
|
||||
end
|
||||
|
||||
skynet.dispatch(function(msg, sz, session, address)
|
||||
local message = { skynet.unpack(msg,sz) }
|
||||
local write_cmd = write_fd .. compose_message(message)
|
||||
local result
|
||||
while true do
|
||||
skynet.send(".connection", write_cmd )
|
||||
result = skynet.call(".connection", readline_fd)
|
||||
if result then
|
||||
break
|
||||
end
|
||||
-- reconnect
|
||||
if init() then
|
||||
skynet.ret(skynet.pack(false , "Disconnected"))
|
||||
return
|
||||
end
|
||||
local function split_package()
|
||||
local result = socket.readline "\r\n"
|
||||
if result == nil then
|
||||
return
|
||||
end
|
||||
local firstchar = string.byte(result)
|
||||
local data = string.sub(result,2)
|
||||
local f = redcmd[firstchar]
|
||||
if f == nil then
|
||||
skynet.ret(skynet.pack(false , "Invalid result"))
|
||||
skynet.send(".connection", close_fd)
|
||||
init()
|
||||
else
|
||||
f(data)
|
||||
assert(f)
|
||||
if f(data) then
|
||||
return
|
||||
end
|
||||
end)
|
||||
socket.yield()
|
||||
return true
|
||||
end
|
||||
|
||||
skynet.filter(
|
||||
function(session, address , msg, sz)
|
||||
if session == 0x7fffffff then
|
||||
socket.push(msg,sz)
|
||||
while split_package() do end
|
||||
elseif session < 0 then
|
||||
local message = { skynet.unpack(msg,sz) }
|
||||
local cmd = compose_message(message)
|
||||
socket.write(cmd)
|
||||
push_request_queue { -session , address }
|
||||
else
|
||||
return session, address, msg , sz
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
skynet.start(init)
|
||||
|
||||
Reference in New Issue
Block a user