1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- ------------------------------------------------------------------------------
- -- 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
|