This is an automated email from the ASF dual-hosted git repository.

shreemaan-abhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 7f5638bb6 fix(limit-count): upgrade redis-cluster lib so NOSCRIPT is 
not treated as node failure (#13579)
7f5638bb6 is described below

commit 7f5638bb6a0e4326232b72b14d7779aac5d65151
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Mon Jun 29 11:31:13 2026 +0800

    fix(limit-count): upgrade redis-cluster lib so NOSCRIPT is not treated as 
node failure (#13579)
---
 apisix-master-0.rockspec             |  2 +-
 apisix/cli/ngx_tpl.lua               |  5 +++
 apisix/init.lua                      |  6 +++
 t/plugin/limit-count-redis-cluster.t | 75 ++++++++++++++++++++++++++++++++++++
 4 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/apisix-master-0.rockspec b/apisix-master-0.rockspec
index a7825837f..2ff4f6c12 100644
--- a/apisix-master-0.rockspec
+++ b/apisix-master-0.rockspec
@@ -63,7 +63,7 @@ dependencies = {
     "base64 = 1.5-3",
     "binaryheap = 0.4-1",
     "api7-dkjson = 0.1.1-0",
-    "resty-redis-cluster = 1.05-1",
+    "lua-resty-redis-cluster = 1.3.3-0",
     "lua-resty-expr = 1.3.2",
     "graphql = 0.0.2-1",
     "argparse = 0.7.1-1",
diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua
index 52574e28d..bbc14c3c7 100644
--- a/apisix/cli/ngx_tpl.lua
+++ b/apisix/cli/ngx_tpl.lua
@@ -331,6 +331,11 @@ http {
     lua_shared_dict plugin-limit-count-reset-header {* 
http.lua_shared_dict["plugin-limit-count"] *};
     {% end %}
 
+    {% if enabled_plugins["limit-conn"] or enabled_plugins["limit-req"] or 
enabled_plugins["limit-count"] then %}
+    # tracks unhealthy redis cluster nodes for fast-fail
+    lua_shared_dict redis_cluster_health 10m;
+    {% end %}
+
     {% if enabled_plugins["graphql-limit-count"] then %}
     lua_shared_dict plugin-graphql-limit-count {* 
http.lua_shared_dict["plugin-graphql-limit-count"] *};
     lua_shared_dict plugin-graphql-limit-count-reset-header {* 
http.lua_shared_dict["plugin-graphql-limit-count-reset-header"] *};
diff --git a/apisix/init.lua b/apisix/init.lua
index f975e71dd..311ba4869 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -168,6 +168,12 @@ function _M.http_init_worker()
     plugin.init_prometheus()
 
     trusted_addresses_util.init_worker()
+
+    local process = require("ngx.process")
+    if process.type() == "privileged agent" then
+        -- start the redis cluster node health checker timer
+        require("resty.rediscluster").init()
+    end
 end
 
 
diff --git a/t/plugin/limit-count-redis-cluster.t 
b/t/plugin/limit-count-redis-cluster.t
index 32785735e..739c65953 100644
--- a/t/plugin/limit-count-redis-cluster.t
+++ b/t/plugin/limit-count-redis-cluster.t
@@ -546,3 +546,78 @@ passed
 ["GET /hello", "GET /hello", "GET /hello", "GET /hello"]
 --- error_code eval
 [200, 200, 503, 503]
+
+
+
+=== TEST 17: set route and flush the cluster script cache
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "uri": "/hello",
+                    "plugins": {
+                        "limit-count": {
+                            "count": 9999,
+                            "time_window": 60,
+                            "key": "remote_addr",
+                            "policy": "redis-cluster",
+                            "redis_cluster_nodes": [
+                                "127.0.0.1:5000",
+                                "127.0.0.1:5001"
+                            ],
+                            "redis_cluster_name": "redis-cluster-1"
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    }
+                }]]
+                )
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
+            -- drop any cached script on every node so the next evalsha 
returns NOSCRIPT
+            local redis = require("resty.redis")
+            local seed = redis:new()
+            seed:set_timeout(1000)
+            local ok, err = seed:connect("127.0.0.1", 5000)
+            if not ok then
+                ngx.say("failed to connect seed: ", err)
+                return
+            end
+            local nodes = seed:cluster("nodes")
+            seed:set_keepalive(10000, 100)
+            for addr in nodes:gmatch("(%d+%.%d+%.%d+%.%d+:%d+)@") do
+                local ip, port = addr:match("([^:]+):(%d+)")
+                local red = redis:new()
+                red:set_timeout(1000)
+                if red:connect(ip, tonumber(port)) then
+                    red:script("flush")
+                    red:set_keepalive(10000, 100)
+                end
+            end
+            ngx.say("done")
+        }
+    }
+--- response_body
+done
+
+
+
+=== TEST 18: cluster path falls back to eval on NOSCRIPT
+--- request
+GET /hello
+--- error_code: 200
+--- grep_error_log eval
+qr/redis evalsha failed:.*Falling back to eval/
+--- grep_error_log_out
+redis evalsha failed: NOSCRIPT No matching script. Please use EVAL.. Falling 
back to eval

Reply via email to