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/08/15 05:27:25 UTC
[apisix] branch master updated: fix: use a new way to manage clean_handler (#7648)
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 768fc7cee fix: use a new way to manage clean_handler (#7648)
768fc7cee is described below
commit 768fc7ceed15e77041480365a7be783b62f4bfa6
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Mon Aug 15 13:27:21 2022 +0800
fix: use a new way to manage clean_handler (#7648)
---
apisix/core/config_etcd.lua | 15 ++++-----------
apisix/core/config_util.lua | 45 ++++++++++++++++++++++++++++++++++++++++-----
apisix/core/config_xds.lua | 8 ++------
apisix/core/config_yaml.lua | 8 ++------
t/core/config_util.t | 39 +++++++++++++++++++++++++++++++++++++++
5 files changed, 87 insertions(+), 28 deletions(-)
diff --git a/apisix/core/config_etcd.lua b/apisix/core/config_etcd.lua
index edb05455c..85cf8d7f4 100644
--- a/apisix/core/config_etcd.lua
+++ b/apisix/core/config_etcd.lua
@@ -21,6 +21,7 @@
local table = require("apisix.core.table")
local config_local = require("apisix.core.config_local")
+local config_util = require("apisix.core.config_util")
local log = require("apisix.core.log")
local json = require("apisix.core.json")
local etcd_apisix = require("apisix.core.etcd")
@@ -314,12 +315,7 @@ local function sync_data(self)
if self.values then
for i, val in ipairs(self.values) do
- if val and val.clean_handlers then
- for _, clean_handler in ipairs(val.clean_handlers) do
- clean_handler(val)
- end
- val.clean_handlers = nil
- end
+ config_util.fire_all_clean_handlers(val)
end
self.values = nil
@@ -406,11 +402,8 @@ local function sync_data(self)
local pre_index = self.values_hash[key]
if pre_index then
local pre_val = self.values[pre_index]
- if pre_val and pre_val.clean_handlers then
- for _, clean_handler in ipairs(pre_val.clean_handlers) do
- clean_handler(pre_val)
- end
- pre_val.clean_handlers = nil
+ if pre_val then
+ config_util.fire_all_clean_handlers(pre_val)
end
if res.value then
diff --git a/apisix/core/config_util.lua b/apisix/core/config_util.lua
index 8a2ce7b57..b3fb13b7c 100644
--- a/apisix/core/config_util.lua
+++ b/apisix/core/config_util.lua
@@ -20,8 +20,10 @@
-- @module core.config_util
local core_tab = require("apisix.core.table")
+local log = require("apisix.core.log")
local str_byte = string.byte
local str_char = string.char
+local ipairs = ipairs
local setmetatable = setmetatable
local tostring = tostring
local type = type
@@ -56,23 +58,56 @@ end
-- or cancelled. Note that Nginx worker exit doesn't trigger the clean handler.
-- Return an index so that we can cancel it later.
function _M.add_clean_handler(item, func)
- local idx = #item.clean_handlers + 1
- item.clean_handlers[idx] = func
- return idx
+ if not item.clean_handlers._id then
+ item.clean_handlers._id = 1
+ end
+
+ local id = item.clean_handlers._id
+ item.clean_handlers._id = item.clean_handlers._id + 1
+ core_tab.insert(item.clean_handlers, {f = func, id = id})
+ return id
end
-- cancel a clean handler added by add_clean_handler.
-- If `fire` is true, call the clean handler.
function _M.cancel_clean_handler(item, idx, fire)
- local f = item.clean_handlers[idx]
- core_tab.remove(item.clean_handlers, idx)
+ local pos, f
+ -- the number of pending clean handler is small so we can cancel them in O(n)
+ for i, clean_handler in ipairs(item.clean_handlers) do
+ if clean_handler.id == idx then
+ pos = i
+ f = clean_handler.f
+ break
+ end
+ end
+
+ if not pos then
+ log.error("failed to find clean_handler with idx ", idx)
+ return
+ end
+
+ core_tab.remove(item.clean_handlers, pos)
if fire then
f(item)
end
end
+-- fire all clean handlers added by add_clean_handler.
+function _M.fire_all_clean_handlers(item)
+ if not item.clean_handlers then
+ return
+ end
+
+ for _, clean_handler in ipairs(item.clean_handlers) do
+ clean_handler.f(item)
+ end
+
+ item.clean_handlers = nil
+end
+
+
---
-- Convert different time units to seconds as time units.
-- Time intervals can be specified in milliseconds, seconds, minutes, hours, days and so on,
diff --git a/apisix/core/config_xds.lua b/apisix/core/config_xds.lua
index 793592b6f..bdb45206a 100644
--- a/apisix/core/config_xds.lua
+++ b/apisix/core/config_xds.lua
@@ -20,6 +20,7 @@
-- @module core.config_xds
local config_local = require("apisix.core.config_local")
+local config_util = require("apisix.core.config_util")
local string = require("apisix.core.string")
local log = require("apisix.core.log")
local json = require("apisix.core.json")
@@ -151,12 +152,7 @@ local function sync_data(self)
if self.values then
for _, val in ipairs(self.values) do
- if val and val.clean_handlers then
- for _, clean_handler in ipairs(val.clean_handlers) do
- clean_handler(val)
- end
- val.clean_handlers = nil
- end
+ config_util.fire_all_clean_handlers(val)
end
self.values = nil
self.values_hash = nil
diff --git a/apisix/core/config_yaml.lua b/apisix/core/config_yaml.lua
index 24a5ff57a..0c6564caf 100644
--- a/apisix/core/config_yaml.lua
+++ b/apisix/core/config_yaml.lua
@@ -20,6 +20,7 @@
-- @module core.config_yaml
local config_local = require("apisix.core.config_local")
+local config_util = require("apisix.core.config_util")
local yaml = require("tinyyaml")
local log = require("apisix.core.log")
local json = require("apisix.core.json")
@@ -142,12 +143,7 @@ local function sync_data(self)
if self.values then
for _, item in ipairs(self.values) do
- if item.clean_handlers then
- for _, clean_handler in ipairs(item.clean_handlers) do
- clean_handler(item)
- end
- item.clean_handlers = nil
- end
+ config_util.fire_all_clean_handlers(item)
end
self.values = nil
end
diff --git a/t/core/config_util.t b/t/core/config_util.t
index 80f01a5d2..2b012fc97 100644
--- a/t/core/config_util.t
+++ b/t/core/config_util.t
@@ -70,3 +70,42 @@ __DATA__
end
}
}
+
+
+
+=== TEST 2: add_clean_handler / cancel_clean_handler / fire_all_clean_handlers
+--- config
+ location /t {
+ content_by_lua_block {
+ local util = require("apisix.core.config_util")
+ local function setup()
+ local item = {clean_handlers = {}}
+ local idx1 = util.add_clean_handler(item, function()
+ ngx.log(ngx.WARN, "fire one")
+ end)
+ local idx2 = util.add_clean_handler(item, function()
+ ngx.log(ngx.WARN, "fire two")
+ end)
+ return item, idx1, idx2
+ end
+
+ local item, idx1, idx2 = setup()
+ util.cancel_clean_handler(item, idx1, true)
+ util.cancel_clean_handler(item, idx2, true)
+
+ local item, idx1, idx2 = setup()
+ util.fire_all_clean_handlers(item)
+
+ local item, idx1, idx2 = setup()
+ util.cancel_clean_handler(item, idx2)
+ util.fire_all_clean_handlers(item)
+
+ local item, idx1, idx2 = setup()
+ util.cancel_clean_handler(item, idx1)
+ util.fire_all_clean_handlers(item)
+ }
+ }
+--- grep_error_log eval
+qr/fire \w+/
+--- grep_error_log_out eval
+"fire one\nfire two\n" x 3