membphis commented on code in PR #14061:
URL: https://github.com/apache/apisix/pull/14061#discussion_r4373484358


##########
apisix/core/lrucache.lua:
##########
@@ -218,41 +263,86 @@ end
 
 
 local function refresh_stale_objs()
+    -- snapshot first: creating an object may yield, and the pool can change
+    -- meanwhile (new stale hits, purge_inactive_objs)
+    local pending = {}
     for lru_obj, keys in pairs(stale_obj_pool) do
         for key, new_obj in pairs(keys) do
-            local obj, err = new_obj.fn(unpack(new_obj.args))
-            if obj ~= nil then
-                lru_obj:set(key, {val = obj, ver = new_obj.ver}, new_obj.ttl)
+            pending[#pending + 1] = {lru_obj, keys, key, new_obj}
+        end
+    end
+
+    for _, item in ipairs(pending) do
+        local lru_obj, keys, key, new_obj = item[1], item[2], item[3], item[4]
+        if keys[key] ~= new_obj then
+            goto continue
+        end
+
+        local ver, ttl = new_obj.ver, new_obj.ttl
+        local obj, err = new_obj.fn(unpack(new_obj.args))
+        if obj ~= nil then
+            -- the item may have been purged while refreshing; writing it back
+            -- then would resurrect it without an access record
+            if keys[key] == new_obj then
+                lru_obj:set(key, {val = obj, ver = ver}, ttl)
                 keys[key] = nil
                 log.info("successfully refresh stale obj for key ",
-                            tostring(key), " to ver ", new_obj.ver)
-            else
-                log.error("failed to refresh stale obj for key ", key, ": ", 
err)
+                            tostring(key), " to ver ", ver)
             end
+        else
+            log.error("failed to refresh stale obj for key ", key, ": ", err)
         end
+
+        ::continue::
     end
 end
 
 
-local function init_worker()
+local function purge_inactive_objs()
+    local now = ngx_now()
+    for lru_obj, inactive_lru in pairs(inactive_lru_pool) do
+        local access_times = inactive_lru.access_times
+        local inactive = inactive_lru.inactive
+        local pending = stale_obj_pool[lru_obj]
+        for key, access_time in pairs(access_times) do
+            if now - access_time > inactive then
+                lru_obj:delete(key)

Review Comment:
   [P2] Preserve stale specs that are still referenced by live resources
   
   This deletes a cached spec based only on request inactivity, even when a 
live Route still references the same spec URL. It introduces an availability 
regression compared with the baseline.
   
   Trigger:
   1. Successfully fetch and cache a remote spec for a Route.
   2. Keep the Route configured, but send no requests for longer than 
`spec_url_ttl`, allowing the purge timer to run. Assume no capacity eviction or 
cache rebuild.
   3. Make the spec endpoint unavailable, then send an otherwise valid request 
to that Route.
   
   Before this PR, the expired entry is still available as a stale object. With 
`refresh_stale = true`, the request is validated against that last-known-good 
spec and continues to the upstream; a refresh is queued in the background, and 
its failure does not fail the current request.
   
   With this PR, `lru_obj:delete(key)` removes that fallback. The next request 
synchronously calls `fetch_and_compile()`; if downloading the spec fails, 
`oas-validator.access()` returns HTTP 500 before proxying. Even when 
downloading succeeds, the request now waits for a remote fetch that previously 
ran in the background. The unchanged business Route and upstream therefore 
acquire an additional runtime dependency after each idle period.
   
   Please fix this before merging. Reclaim specs only after no effective 
resource references their cache key, while preserving stale serving and 
background refresh for specs that are still referenced, or use another design 
that preserves the same request availability without a synchronous refetch. Add 
a regression test covering successful caching, an idle period beyond the TTL, 
and a subsequent request while the spec endpoint is unavailable, alongside the 
unused-spec reclamation tests.
   



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to