bzp2010 commented on code in PR #12214:
URL: https://github.com/apache/apisix/pull/12214#discussion_r2094929685


##########
apisix/core/config_yaml.lua:
##########
@@ -158,29 +149,59 @@ local function sync_data(self)
         return nil, "missing 'key' arguments"
     end
 
-    if not apisix_yaml_mtime then
-        log.warn("wait for more time")
-        return nil, "failed to read local file " .. apisix_yaml_path
+    local conf_version
+    if is_use_admin_api() then
+        conf_version = apisix_yaml[self.conf_version_key] or 0
+    else
+        if not apisix_yaml_mtime then
+            log.warn("wait for more time")
+            return nil, "failed to read local file " .. apisix_yaml_path
+        end
+        conf_version = apisix_yaml_mtime
     end
 
-    if self.conf_version == apisix_yaml_mtime then
+    if not conf_version or conf_version == self.conf_version then
         return true
     end
 
     local items = apisix_yaml[self.key]
-    log.info(self.key, " items: ", json.delay_encode(items))
     if not items then
         self.values = new_tab(8, 0)
         self.values_hash = new_tab(0, 8)
-        self.conf_version = apisix_yaml_mtime
+        self.conf_version = conf_version
         return true
     end
 
-    if self.values then
-        for _, item in ipairs(self.values) do
-            config_util.fire_all_clean_handlers(item)
+    if self.values and #self.values > 0 then
+        if is_use_admin_api() then
+            -- used to delete values that do not exist in the new list.
+            -- only when using modifiedIndex, old values need to be retained.
+            -- If modifiedIndex changes, old values need to be removed and 
cleaned up.
+            local exist_modifiedIndex_items = {}
+            for _, item in ipairs(items) do
+                if item.modifiedIndex then
+                    exist_modifiedIndex_items[tostring(item.id)] = true
+                end
+            end
+
+            local new_values = new_tab(8, 0)
+            self.values_hash = new_tab(0, 8)
+            for _, item in ipairs(self.values) do
+                local id = item.value.id
+                if not exist_modifiedIndex_items[id]  then
+                    config_util.fire_all_clean_handlers(item)
+                else

Review Comment:
   A correct process is:
   1. Check which resources (of ids) existed in the old configuration set but 
not in the new configuration set, which means that these resources need to be 
removed and cleaned up.
   2. check which resources exist in both the old and new configuration sets, 
but have inconsistent modifiedIndex, meaning they need to be updated.
   3. check for resources that exist in the new configuration set but not in 
the old, meaning they need to be created.
   
   Where 1, should be realized by the resource id, not the modifiedIndex, they 
have nothing to do with each other. The actual situation is that if for a given 
resource id, if the id is changed to some other value, it means deleting a 
resource represented by the old id and creating a resource represented by the 
new id, which would be the simplest and most reliable pattern.
   
   ADC's "differ" is the exact implementation of this idea. Except that it 
allows a comparison range beyond modifiedIndex, and you can check its code and 
implement a simple equivalent.
   
https://github.com/api7/adc/blob/main/apps/cli/src/differ/differv3.ts#L308-L639



##########
apisix/core/config_yaml.lua:
##########
@@ -256,12 +281,26 @@ local function sync_data(self)
             end
 
             if data_valid then
-                insert_tab(self.values, conf_item)
-                local item_id = conf_item.value.id or self.key .. "#" .. id
-                item_id = tostring(item_id)
-                self.values_hash[item_id] = #self.values
-                conf_item.value.id = item_id
-                conf_item.clean_handlers = {}
+                local item_id = tostring(id)
+                local pre_index = self.values_hash[item_id]
+                if pre_index then
+                    -- remove the old item
+                    local pre_val = self.values[pre_index]
+                    if pre_val and
+                        (not pre_val.modifiedIndex or pre_val.modifiedIndex ~= 
modifiedIndex) then
+                        log.error("fire all clean handlers for ", self.key, " 
id: ", id,
+                                    " modifiedIndex: ", modifiedIndex)
+                        config_util.fire_all_clean_handlers(pre_val)
+                        self.values[pre_index] = conf_item
+                        conf_item.value.id = item_id
+                        conf_item.clean_handlers = {}
+                    end

Review Comment:
   Since self.values has been overwritten with a new table above (different 
pointer address), what is this dealing with?



##########
apisix/core/config_yaml.lua:
##########
@@ -158,29 +149,59 @@ local function sync_data(self)
         return nil, "missing 'key' arguments"
     end
 
-    if not apisix_yaml_mtime then
-        log.warn("wait for more time")
-        return nil, "failed to read local file " .. apisix_yaml_path
+    local conf_version
+    if is_use_admin_api() then
+        conf_version = apisix_yaml[self.conf_version_key] or 0
+    else
+        if not apisix_yaml_mtime then
+            log.warn("wait for more time")
+            return nil, "failed to read local file " .. apisix_yaml_path
+        end
+        conf_version = apisix_yaml_mtime
     end
 
-    if self.conf_version == apisix_yaml_mtime then
+    if not conf_version or conf_version == self.conf_version then
         return true
     end
 
     local items = apisix_yaml[self.key]
-    log.info(self.key, " items: ", json.delay_encode(items))
     if not items then
         self.values = new_tab(8, 0)
         self.values_hash = new_tab(0, 8)
-        self.conf_version = apisix_yaml_mtime
+        self.conf_version = conf_version
         return true
     end
 
-    if self.values then
-        for _, item in ipairs(self.values) do
-            config_util.fire_all_clean_handlers(item)
+    if self.values and #self.values > 0 then
+        if is_use_admin_api() then
+            -- used to delete values that do not exist in the new list.
+            -- only when using modifiedIndex, old values need to be retained.
+            -- If modifiedIndex changes, old values need to be removed and 
cleaned up.
+            local exist_modifiedIndex_items = {}
+            for _, item in ipairs(items) do
+                if item.modifiedIndex then
+                    exist_modifiedIndex_items[tostring(item.id)] = true
+                end
+            end
+
+            local new_values = new_tab(8, 0)
+            self.values_hash = new_tab(0, 8)
+            for _, item in ipairs(self.values) do
+                local id = item.value.id
+                if not exist_modifiedIndex_items[id]  then
+                    config_util.fire_all_clean_handlers(item)
+                else
+                    insert_tab(new_values, item)
+                    self.values_hash[id] = #new_values
+                end
+            end
+            self.values = new_values

Review Comment:
   Why is the new value set here? Shouldn't it be set after the schema check 
below?



##########
apisix/core/config_yaml.lua:
##########
@@ -158,29 +149,59 @@ local function sync_data(self)
         return nil, "missing 'key' arguments"
     end
 
-    if not apisix_yaml_mtime then
-        log.warn("wait for more time")
-        return nil, "failed to read local file " .. apisix_yaml_path
+    local conf_version
+    if is_use_admin_api() then
+        conf_version = apisix_yaml[self.conf_version_key] or 0
+    else
+        if not apisix_yaml_mtime then
+            log.warn("wait for more time")
+            return nil, "failed to read local file " .. apisix_yaml_path
+        end
+        conf_version = apisix_yaml_mtime
     end
 
-    if self.conf_version == apisix_yaml_mtime then
+    if not conf_version or conf_version == self.conf_version then
         return true
     end
 
     local items = apisix_yaml[self.key]
-    log.info(self.key, " items: ", json.delay_encode(items))
     if not items then
         self.values = new_tab(8, 0)
         self.values_hash = new_tab(0, 8)
-        self.conf_version = apisix_yaml_mtime
+        self.conf_version = conf_version
         return true
     end
 
-    if self.values then
-        for _, item in ipairs(self.values) do
-            config_util.fire_all_clean_handlers(item)
+    if self.values and #self.values > 0 then
+        if is_use_admin_api() then
+            -- used to delete values that do not exist in the new list.
+            -- only when using modifiedIndex, old values need to be retained.
+            -- If modifiedIndex changes, old values need to be removed and 
cleaned up.
+            local exist_modifiedIndex_items = {}
+            for _, item in ipairs(items) do
+                if item.modifiedIndex then
+                    exist_modifiedIndex_items[tostring(item.id)] = true
+                end
+            end
+
+            local new_values = new_tab(8, 0)
+            self.values_hash = new_tab(0, 8)
+            for _, item in ipairs(self.values) do
+                local id = item.value.id
+                if not exist_modifiedIndex_items[id]  then
+                    config_util.fire_all_clean_handlers(item)
+                else

Review Comment:
   Why does resource cleanup use `modifiedIndex` to determine if a resource 
needs to be deleted?
   They don't seem to be related, it should be based on the resource id, such 
as the route id or consumer username.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@apisix.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to