You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by we...@apache.org on 2020/09/17 01:30:59 UTC

[apisix] branch master updated: bugfix: clear all cached object when got `delete` action, and removing (#2168)

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

wenming 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 68b1f9c  bugfix: clear all cached object when got `delete` action, and removing (#2168)
68b1f9c is described below

commit 68b1f9cc57c3320ff814859ce66f4cfd401e10ae
Author: YuanSheng Wang <me...@gmail.com>
AuthorDate: Thu Sep 17 09:30:44 2020 +0800

    bugfix: clear all cached object when got `delete` action, and removing (#2168)
    
    stale boolean data in table `self.values` with a safer way.
---
 apisix/core/config_etcd.lua |  25 ++++++----
 t/node/route-delete.t       | 109 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+), 8 deletions(-)

diff --git a/apisix/core/config_etcd.lua b/apisix/core/config_etcd.lua
index b651ea9..d058277 100644
--- a/apisix/core/config_etcd.lua
+++ b/apisix/core/config_etcd.lua
@@ -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
 
diff --git a/t/node/route-delete.t b/t/node/route-delete.t
new file mode 100644
index 0000000..2111198
--- /dev/null
+++ b/t/node/route-delete.t
@@ -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