Skip to content
Permalink
Browse files
fix: use a new way to manage clean_handler (#7648)
  • Loading branch information
spacewander committed Aug 15, 2022
1 parent 689e4f1 commit 768fc7ceed15e77041480365a7be783b62f4bfa6
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 28 deletions.
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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

0 comments on commit 768fc7c

Please sign in to comment.