Parcourir la source

redis client module added. pubsub so far

Vladimir Dronnikov il y a 9 ans
Parent
commit
edc7eaf3ff
1 fichiers modifiés avec 83 ajouts et 0 suppressions
  1. 83 0
      lua_modules/redis/redis.lua

+ 83 - 0
lua_modules/redis/redis.lua

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