bugfix: clear all cached object when got delete action, and removing (#2168)

stale boolean data in table `self.values` with a safer way.
This commit is contained in:
YuanSheng Wang 2020-09-17 09:30:44 +08:00 committed by GitHub
parent e93cdbd48a
commit 68b1f9cc57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 126 additions and 8 deletions

View File

@ -14,6 +14,8 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local table = require("apisix.core.table")
local config_local = require("apisix.core.config_local")
local log = require("apisix.core.log")
local json = require("apisix.core.json")
@ -338,10 +340,13 @@ local function sync_data(self)
res.value.id = key
self.values[pre_index] = res
res.clean_handlers = {}
log.info("update data by key: ", key)
else
self.sync_times = self.sync_times + 1
self.values[pre_index] = false
self.values_hash[key] = nil
log.info("delete data by key: ", key)
end
elseif res.value then
@ -349,25 +354,29 @@ local function sync_data(self)
insert_tab(self.values, res)
self.values_hash[key] = #self.values
res.value.id = key
log.info("insert data by key: ", key)
end
-- avoid space waste
-- todo: need to cover this path, it is important.
if self.sync_times > 100 then
local count = 0
for i = 1, #self.values do
local val = self.values[i]
self.values[i] = nil
local values_original = table.clone(self.values)
table.clear(self.values)
for i = 1, #values_original do
local val = values_original[i]
if val then
count = count + 1
self.values[count] = val
table.insert(self.values, val)
end
end
for i = 1, count do
table.clear(self.values_hash)
log.info("clear stale data in `values_hash` for key: ", key)
for i = 1, #self.values do
key = short_key(self, self.values[i].key)
self.values_hash[key] = i
end
self.sync_times = 0
end

109
t/node/route-delete.t Normal file
View File

@ -0,0 +1,109 @@
#
# 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';
repeat_each(2);
log_level('info');
worker_connections(256);
no_root_location();
no_shuffle();
run_tests();
__DATA__
=== TEST 1: create 130 routes + delete them
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
for i = 1, 130 do
local code, body = t('/apisix/admin/routes/' .. i,
ngx.HTTP_PUT,
[[{
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello]] .. i .. [["
}]]
)
end
for i = 1, 130 do
local code, body = t('/apisix/admin/routes/' .. i,
ngx.HTTP_PUT,
[[{
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello]] .. i .. [["
}]]
)
end
for i = 1, 130 do
local code, body = t('/apisix/admin/routes/' .. i,
ngx.HTTP_DELETE
)
end
for i = 1, 130 do
local code, body = t('/apisix/admin/routes/' .. i,
ngx.HTTP_PUT,
[[{
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello]] .. i .. [["
}]]
)
end
for i = 1, 130 do
local code, body = t('/apisix/admin/routes/' .. i,
ngx.HTTP_DELETE
)
end
ngx.say("done")
}
}
--- request
GET /t
--- response_body
done
--- no_error_log
[error]
--- grep_error_log eval
qr/\w+ (data by key: 126)/
--- grep_error_log_out
insert data by key: 126
update data by key: 126
delete data by key: 126
insert data by key: 126
delete data by key: 126
--- timeout: 20