From 492c40977a23ac5a90ca4e1c2b98935102433556 Mon Sep 17 00:00:00 2001 From: spacewander Date: Tue, 6 Sep 2022 11:09:17 +0800 Subject: [PATCH] feat: call `destroy` method when Nginx exits So we can do some clean up job in the plugin. Signed-off-by: spacewander --- apisix/init.lua | 3 ++ apisix/plugin.lua | 18 ++++++++++++ docs/en/latest/plugin-develop.md | 2 +- docs/zh/latest/plugin-develop.md | 2 +- t/node/plugin.t | 48 ++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 t/node/plugin.t diff --git a/apisix/init.lua b/apisix/init.lua index c6ddf7c4fbff..80621432c03b 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -152,6 +152,9 @@ end function _M.http_exit_worker() + -- TODO: we can support stream plugin later - currently there is not `destory` method + -- in stream plugins + plugin.exit_worker() require("apisix.plugins.ext-plugin.init").exit_worker() end diff --git a/apisix/plugin.lua b/apisix/plugin.lua index a0fd0719fa49..3cf2283a9aae 100644 --- a/apisix/plugin.lua +++ b/apisix/plugin.lua @@ -356,6 +356,24 @@ function _M.load(config) end +function _M.exit_worker() + for name, plugin in pairs(local_plugins_hash) do + local ty = PLUGIN_TYPE_HTTP + if plugin.type == "wasm" then + ty = PLUGIN_TYPE_HTTP_WASM + end + unload_plugin(name, ty) + end + + -- we need to load stream plugin so that we can check their schemas in + -- Admin API. Maybe we can avoid calling `load` in this case? So that + -- we don't need to call `destroy` too + for name in pairs(stream_local_plugins_hash) do + unload_plugin(name, PLUGIN_TYPE_STREAM) + end +end + + local function trace_plugins_info_for_debug(ctx, plugins) if not enable_debug() then return diff --git a/docs/en/latest/plugin-develop.md b/docs/en/latest/plugin-develop.md index debf8e7677eb..ca1d3a23f019 100644 --- a/docs/en/latest/plugin-develop.md +++ b/docs/en/latest/plugin-develop.md @@ -90,7 +90,7 @@ nginx_config: ``` The plugin itself provides the init method. It is convenient for plugins to perform some initialization after -the plugin is loaded. +the plugin is loaded. If you need to clean up the initialization, you can put it in the corresponding destroy method. Note : if the dependency of some plugin needs to be initialized when Nginx start, you may need to add logic to the initialization method "http_init" in the file __apisix/init.lua__, and you may need to add some processing on generated part of Nginx diff --git a/docs/zh/latest/plugin-develop.md b/docs/zh/latest/plugin-develop.md index 855eb9bb751a..d9e5705156cd 100644 --- a/docs/zh/latest/plugin-develop.md +++ b/docs/zh/latest/plugin-develop.md @@ -86,7 +86,7 @@ nginx_config: lua_shared_dict introspection 10m; # cache for JWT verification results ``` -插件本身提供了 init 方法。方便插件加载后做初始化动作。 +插件本身提供了 init 方法。方便插件加载后做初始化动作。如果你需要清理初始化动作创建出来的内容,你可以在对应的 destroy 方法里完成这一操作。 注:如果部分插件的功能实现,需要在 Nginx 初始化启动,则可能需要在 __apisix/init.lua__ 文件的初始化方法 http_init 中添加逻辑,并且可能需要在 __apisix/cli/ngx_tpl.lua__ 文件中,对 Nginx 配置文件生成的部分,添加一些你需要的处理。但是这样容易对全局产生影响,根据现有的插件机制,**我们不建议这样做,除非你已经对代码完全掌握**。 diff --git a/t/node/plugin.t b/t/node/plugin.t new file mode 100644 index 000000000000..f2c54c72bd56 --- /dev/null +++ b/t/node/plugin.t @@ -0,0 +1,48 @@ +# +# 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'; + +add_block_preprocessor(sub { + my ($block) = @_; + + if (!$block->request) { + $block->set_value("request", "GET /t"); + } + + if ((!defined $block->error_log) && (!defined $block->no_error_log)) { + $block->set_value("no_error_log", "[error]"); + } + + $block; +}); + +run_tests; + +__DATA__ + +=== TEST 1: set custom log format +--- extra_init_by_lua + local exp = require("apisix.plugins.example-plugin") + exp.destroy = function() + ngx.log(ngx.WARN, "destroy method called") + end +--- config + location /t { + return 200 "dummy"; + } +--- shutdown_error_log +destroy method called