nic-6443 opened a new pull request, #14061: URL: https://github.com/apache/apisix/pull/14061
### Description `oas-validator` caches specs fetched from `spec_url` in a per-worker lrucache keyed by the URL (plus `ssl_verify` and a hash of the request headers), with `count = 512` and no memory bound. Every distinct URL adds a fully compiled copy, and a URL that is no longer requested stays cached until count eviction, since resty.lrucache only expires entries lazily. With large specs a compiled copy is easily 10+ MB, so a route whose `spec_url` changes over time (e.g. a versioned spec URL) grows worker memory on every change until the process is OOM-killed. The cache is now keyed by the resource that declares the plugin (`conf._meta.parent.resource_key`, which `set_plugins_meta_parent` sets for routes, services, consumers, consumer groups, plugin configs and global rules), with the URL key as the version. When a resource switches to another URL its slot is overwritten, so the old compiled spec loses its last reference right away. If a conf has no parent, the URL-keyed behavior is kept. To keep sharing one compiled spec across resources that declare the same URL, compiled entries are also kept in a weak-valued table keyed by the URL key. A new slot reuses an entry from there only while it is younger than `spec_url_ttl`, so the TTL refresh still refetches the spec. Stale serving, background refresh and serial creation are unchanged. There is a second leak on the same path: changing `spec_url_ttl` in the plugin metadata rebuilds the lrucache, but `core.lrucache` keeps every lrucache it ever created as a key of its internal `stale_obj_pool`, so the old cache and every spec in it stay alive forever. That pool is now weak-keyed. Its values (pending refresh jobs) do not reference the lrucache itself, so a dropped lrucache can be collected; lrucaches that are still in use are unaffected. Tests assert release through fetch counts on the local spec server, not memory numbers: - changing a route's `spec_url` and running a full GC makes another route declaring the old URL fetch it again (on master it is served from the URL-keyed cache, so the count stays at 1) - two routes declaring the same URL fetch it once - after changing `spec_url_ttl` and a full GC, a spec held only by the previous cache is fetched again - with a 1s TTL and two routes sharing one URL, the background refresh still refetches the spec - `t/core/lrucache.t`: an lrucache dropped by its owner releases its cached objects ### Checklist - [x] I have explained the need for this PR and the problem it solves - [x] I have explained the changes or the new features added to this PR - [x] I have added tests corresponding to this change - [x] I have updated the documentation to reflect this change - [x] I have verified that this change is backward compatible (If not, please discuss on the [APISIX mailing list](https://github.com/apache/apisix/tree/master#community) first) -- 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]
