You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2022/12/02 08:16:31 UTC

[apisix] branch master updated: fix(ai): remove BUILD_ROUTER event when ai module is unloaded (#8184)

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

spacewander 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 2ffce7d71 fix(ai): remove BUILD_ROUTER event when ai module is unloaded (#8184)
2ffce7d71 is described below

commit 2ffce7d7160b7927411557fb8b6d5cb64d48d004
Author: soulbird <zh...@outlook.com>
AuthorDate: Fri Dec 2 16:16:26 2022 +0800

    fix(ai): remove BUILD_ROUTER event when ai module is unloaded (#8184)
    
    Co-authored-by: soulbird <zh...@gmail.com>
---
 apisix/core/event.lua                              |   4 +
 apisix/http/router/radixtree_host_uri.lua          |   2 +
 apisix/http/router/radixtree_uri.lua               |   2 +
 .../http/router/radixtree_uri_with_parameter.lua   |   2 +
 apisix/plugins/ai.lua                              |   6 +-
 t/plugin/ai5.t                                     | 270 +++++++++++++++++++++
 6 files changed, 284 insertions(+), 2 deletions(-)

diff --git a/apisix/core/event.lua b/apisix/core/event.lua
index 38459ff11..006cd1a0a 100644
--- a/apisix/core/event.lua
+++ b/apisix/core/event.lua
@@ -38,4 +38,8 @@ function _M.register(type, handler)
     events[type] = handler
 end
 
+function _M.unregister(type)
+    events[type] = nil
+end
+
 return _M
diff --git a/apisix/http/router/radixtree_host_uri.lua b/apisix/http/router/radixtree_host_uri.lua
index 449a6ccdb..70919763c 100644
--- a/apisix/http/router/radixtree_host_uri.lua
+++ b/apisix/http/router/radixtree_host_uri.lua
@@ -155,6 +155,8 @@ end
 
 
 function _M.matching(api_ctx)
+    core.log.info("route match mode: radixtree_host_uri")
+
     core.table.clear(match_opts)
     match_opts.method = api_ctx.var.request_method
     match_opts.remote_addr = api_ctx.var.remote_addr
diff --git a/apisix/http/router/radixtree_uri.lua b/apisix/http/router/radixtree_uri.lua
index 25789a4a3..6e546364a 100644
--- a/apisix/http/router/radixtree_uri.lua
+++ b/apisix/http/router/radixtree_uri.lua
@@ -50,6 +50,8 @@ end
 
 
 function _M.matching(api_ctx)
+    core.log.info("route match mode: radixtree_uri")
+
     return base_router.match_uri(uri_router, match_opts, api_ctx)
 end
 
diff --git a/apisix/http/router/radixtree_uri_with_parameter.lua b/apisix/http/router/radixtree_uri_with_parameter.lua
index 696c74f0b..4bf7f3ebe 100644
--- a/apisix/http/router/radixtree_uri_with_parameter.lua
+++ b/apisix/http/router/radixtree_uri_with_parameter.lua
@@ -50,6 +50,8 @@ end
 
 
 function _M.matching(api_ctx)
+    core.log.info("route match mode: radixtree_uri_with_parameter")
+
     return base_router.match_uri(uri_router, match_opts, api_ctx)
 end
 
diff --git a/apisix/plugins/ai.lua b/apisix/plugins/ai.lua
index afbda31d4..3195b4bae 100644
--- a/apisix/plugins/ai.lua
+++ b/apisix/plugins/ai.lua
@@ -73,6 +73,8 @@ end
 
 
 local function ai_router_http_matching(api_ctx)
+    core.log.info("route match mode: ai_match")
+
     local key = get_cache_key_func(api_ctx)
     core.log.info("route cache key: ", key)
     local api_ctx_cache = route_lrucache(key, nil,
@@ -296,8 +298,6 @@ end
 
 
 function _M.destroy()
-    -- TODO: add test cases to cover this function
-    -- if the ai plugin is disabled at runtime, all functions replaced by the ai plugin are restored
     if orig_router_http_matching then
         router.router_http.matching = orig_router_http_matching
         orig_router_http_matching = nil
@@ -312,6 +312,8 @@ function _M.destroy()
         apisix.http_balancer_phase = orig_http_balancer_phase
         orig_http_balancer_phase = nil
     end
+
+    event.unregister(event.CONST.BUILD_ROUTER)
 end
 
 
diff --git a/t/plugin/ai5.t b/t/plugin/ai5.t
new file mode 100644
index 000000000..24282c4cb
--- /dev/null
+++ b/t/plugin/ai5.t
@@ -0,0 +1,270 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+log_level('info');
+worker_connections(256);
+no_root_location();
+no_shuffle();
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+
+    if (!defined $block->extra_init_by_lua) {
+        my $extra_init_by_lua = <<_EOC_;
+        unload_ai_module = function ()
+            local t = require("lib.test_admin").test
+            local data = [[
+deployment:
+  role: traditional
+  role_traditional:
+    config_provider: etcd
+  admin:
+    admin_key: null
+apisix:
+  node_listen: 1984
+plugins:
+            ]]
+            require("lib.test_admin").set_config_yaml(data)
+
+            local code, body = t('/apisix/admin/plugins/reload',
+                                    ngx.HTTP_PUT)
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+        end
+
+        load_ai_module = function ()
+            local t = require("lib.test_admin").test
+            local data = [[
+deployment:
+  role: traditional
+  role_traditional:
+    config_provider: etcd
+  admin:
+    admin_key: null
+apisix:
+  node_listen: 1984
+plugins:
+  - ai
+            ]]
+            require("lib.test_admin").set_config_yaml(data)
+
+            local code, body = t('/apisix/admin/plugins/reload',
+                                    ngx.HTTP_PUT)
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+        end
+_EOC_
+
+        $block->set_value("extra_init_by_lua", $extra_init_by_lua);
+    }
+
+    if ((!defined $block->error_log) && (!defined $block->no_error_log)) {
+        $block->set_value("no_error_log", "[error]");
+    }
+
+    if (!defined $block->request) {
+        $block->set_value("request", "GET /t");
+    }
+
+});
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: enable(default) -> disable -> enable
+--- http_config eval: $::HttpConfig
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            -- register route
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "host": "127.0.0.1",
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/hello"
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+            -- enable route cache
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200)
+
+            -- disable ai plugin
+            unload_ai_module()
+
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200)
+
+            -- enable ai plugin
+            load_ai_module()
+
+            -- TODO: The route cache should be enabled, but since no new routes are registered,
+            -- the route tree is not rebuilt,
+            -- so it is not possible to switch to route cache mode, we should fix it
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200, "enable: access /hello")
+
+            -- register a new route and trigger a route tree rebuild
+            local code, body = t('/apisix/admin/routes/2',
+                ngx.HTTP_PUT,
+                [[{
+                    "host": "127.0.0.1",
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/echo"
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200)
+
+            ngx.say("done")
+        }
+    }
+--- response_body
+done
+--- grep_error_log eval
+qr/route match mode: \S[^,]+/
+--- grep_error_log_out
+route match mode: ai_match
+route match mode: radixtree_uri
+route match mode: radixtree_uri
+route match mode: radixtree_uri
+route match mode: ai_match
+route match mode: radixtree_uri
+
+
+
+=== TEST 2: disable(default) -> enable -> disable
+--- yaml_config
+deployment:
+  role: traditional
+  role_traditional:
+    config_provider: etcd
+  admin:
+    admin_key: null
+apisix:
+  node_listen: 1984
+plugins:
+--- http_config eval: $::HttpConfig
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            -- register route
+            local code, body = t('/apisix/admin/routes/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "host": "127.0.0.1",
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/hello"
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200)
+
+            -- enable ai plugin
+            load_ai_module()
+
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200)
+
+            -- register a new route and trigger a route tree rebuild
+            local code, body = t('/apisix/admin/routes/2',
+                ngx.HTTP_PUT,
+                [[{
+                    "host": "127.0.0.1",
+                    "methods": ["GET"],
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/echo"
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200)
+
+            -- disable ai plugin
+            unload_ai_module()
+
+            local code = t('/hello', ngx.HTTP_GET)
+            assert(code == 200)
+
+            ngx.say("done")
+        }
+    }
+--- response_body
+done
+--- grep_error_log eval
+qr/route match mode: \S[^,]+/
+--- grep_error_log_out
+route match mode: radixtree_uri
+route match mode: radixtree_uri
+route match mode: ai_match
+route match mode: radixtree_uri
+route match mode: radixtree_uri