redis client module added. pubsub so far

This commit is contained in:
Vladimir Dronnikov 2015-02-06 22:22:37 +03:00
parent 165e91e60d
commit edc7eaf3ff
1 changed files with 83 additions and 0 deletions

View File

@ -0,0 +1,83 @@
------------------------------------------------------------------------------
-- Redis client module
--
-- LICENCE: http://opensource.org/licenses/MIT
-- Vladimir Dronnikov <dronnikov@gmail.com>
--
-- Example:
-- local redis = dofile("redis.lua").connect(host, port)
-- redis:publish("chan1", foo")
-- redis:subscribe("chan1", function(channel, msg) print(channel, msg) end)
------------------------------------------------------------------------------
local M
do
-- const
local REDIS_PORT = 6379
-- cache
local pairs, tonumber = pairs, tonumber
--
local publish = function(self, chn, s)
self._fd:send(("*3\r\n$7\r\npublish\r\n$%d\r\n%s\r\n$%d\r\n%s\r\n"):format(
#chn, chn, #s, s
))
-- TODO: confirmation? then queue of answers needed
end
local subscribe = function(self, chn, handler)
-- TODO: subscription to all channels, with single handler
self._fd:send(("*2\r\n$9\r\nsubscribe\r\n$%d\r\n%s\r\n"):format(
#chn, chn
))
self._handlers[chn] = handler
-- TODO: confirmation? then queue of answers needed
end
local unsubscribe = function(self, chn)
self._handlers[chn] = false
end
-- NB: pity we can not just augment what net.createConnection returns
local close = function(self)
self._fd:close()
end
local connect = function(host, port)
local _fd = net.createConnection(net.TCP, 0)
local self = {
_fd = _fd,
_handlers = { },
-- TODO: consider metatables?
close = close,
publish = publish,
subscribe = subscribe,
unsubscribe = unsubscribe,
}
_fd:on("connection", function()
--print("+FD")
end)
_fd:on("disconnection", function()
-- FIXME: this suddenly occurs. timeout?
--print("-FD")
end)
_fd:on("receive", function(fd, s)
--print("IN", s)
-- TODO: subscription to all channels
-- lookup message pattern to determine channel and payload
-- NB: pairs() iteration gives no fixed order!
for chn, handler in pairs(self._handlers) do
local p = ("*3\r\n$7\r\nmessage\r\n$%d\r\n%s\r\n$"):format(#chn, chn)
if s:find(p, 1, true) then
-- extract and check message length
-- NB: only the first TCP packet considered!
local _, start, len = s:find("(%d-)\r\n", #p)
if start and tonumber(len) == #s - start - 2 and handler then
handler(chn, s:sub(start + 1, -2)) -- ends with \r\n
end
end
end
end)
_fd:connect(port or REDIS_PORT, host)
return self
end
-- expose
M = {
connect = connect,
}
end
return M