membphis commented on code in PR #12872:
URL: https://github.com/apache/apisix/pull/12872#discussion_r2719225572


##########
apisix/plugins/limit-conn/util.lua:
##########
@@ -18,36 +18,76 @@
 local assert            = assert
 local math              = require "math"
 local floor             = math.floor
+local ngx               = ngx
+local ngx_time          = ngx.time
+local uuid              = require("resty.jit-uuid")
+local core              = require("apisix.core")
+local hex_encode        = require("resty.string").to_hex
+
 local _M = {version = 0.3}
+local redis_incoming_script = core.string.compress_script([=[
+    local key = KEYS[1]
+    local limit = tonumber(ARGV[1])
+    local ttl = tonumber(ARGV[2])
+    local now = tonumber(ARGV[3])
+    local req_id = ARGV[4]
+
+    redis.call('ZREMRANGEBYSCORE', key, 0, now)
+
+    local count = redis.call('ZCARD', key)
+    if count >= limit then
+        return {0, count}
+    end
+
+    redis.call('ZADD', key, now + ttl, req_id)
+    redis.call('EXPIRE', key, ttl)
+    return {1, count + 1}
+]=])
+local redis_incoming_script_sha = 
hex_encode(ngx.sha1_bin(redis_incoming_script))
 
 
 function _M.incoming(self, red, key, commit)
     local max = self.max
     self.committed = false
+    local raw_key = key
     key = "limit_conn" .. ":" .. key
 
-    local conn, err
+    local conn
     if commit then
-        conn, err = red:incrby(key, 1)
-        if not conn then
+        local req_id = ngx.ctx.request_id or uuid.generate_v4()
+        if not ngx.ctx.limit_conn_req_ids then
+            ngx.ctx.limit_conn_req_ids = {}
+        end
+        ngx.ctx.limit_conn_req_ids[raw_key] = req_id
+
+        local now = ngx_time()
+        local res, err = red:evalsha(redis_incoming_script_sha, 1, key,

Review Comment:
   it is more safer than we generate it by `ngx api`



##########
apisix/plugins/limit-conn/util.lua:
##########
@@ -18,36 +18,76 @@
 local assert            = assert
 local math              = require "math"
 local floor             = math.floor
+local ngx               = ngx
+local ngx_time          = ngx.time
+local uuid              = require("resty.jit-uuid")
+local core              = require("apisix.core")
+local hex_encode        = require("resty.string").to_hex
+
 local _M = {version = 0.3}
+local redis_incoming_script = core.string.compress_script([=[
+    local key = KEYS[1]
+    local limit = tonumber(ARGV[1])
+    local ttl = tonumber(ARGV[2])
+    local now = tonumber(ARGV[3])
+    local req_id = ARGV[4]
+
+    redis.call('ZREMRANGEBYSCORE', key, 0, now)
+
+    local count = redis.call('ZCARD', key)
+    if count >= limit then
+        return {0, count}
+    end
+
+    redis.call('ZADD', key, now + ttl, req_id)
+    redis.call('EXPIRE', key, ttl)
+    return {1, count + 1}
+]=])
+local redis_incoming_script_sha = 
hex_encode(ngx.sha1_bin(redis_incoming_script))
 
 
 function _M.incoming(self, red, key, commit)
     local max = self.max
     self.committed = false
+    local raw_key = key
     key = "limit_conn" .. ":" .. key
 
-    local conn, err
+    local conn
     if commit then
-        conn, err = red:incrby(key, 1)
-        if not conn then
+        local req_id = ngx.ctx.request_id or uuid.generate_v4()
+        if not ngx.ctx.limit_conn_req_ids then
+            ngx.ctx.limit_conn_req_ids = {}
+        end
+        ngx.ctx.limit_conn_req_ids[raw_key] = req_id
+
+        local now = ngx_time()
+        local res, err = red:evalsha(redis_incoming_script_sha, 1, key,

Review Comment:
   another example, gen the sha1 by `redis:script`:
   
   ```lua
   local function fetch_latest_redis_script_sha1()
       if redis_incoming_script_sha then
           return redis_incoming_script_sha
       end
       
       local sha1, load_err = red:script("LOAD", lua_script)
       if load_err then
           return nil, load_err
       end
   
       redis_incoming_script_sha = sha1
       return redis_incoming_script_sha
   end
   
   local sha1, err = fetch_latest_redis_script_sha1()
   if not sha1 then
       ngx.log(ngx.ERR, "Failed to load Lua script into Redis: ", err)
       return nil, err
   end
   
   local res, err = red:evalsha(sha1, ...)
   if err and core.string.has_prefix(err, "NOSCRIPT") then
       redis_incoming_script_sha = nil
   end



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to