Aias00 opened a new issue, #7714: URL: https://github.com/apache/shenyu/issues/7714
### Current behavior The request path lazily initializes selector-specific cache backends using a non-atomic `get` followed by `init`. Two first requests can both observe no cache and both build a backend. `ApplicationConfigCache.init()` unconditionally `put`s the result; the overwritten backend is never closed. ### Locations / flow - [CachePlugin.getCache():122–130](https://github.com/apache/shenyu/blob/66d7d954ca37d651a5ad916f988a8081157a7ab4/shenyu-plugin/shenyu-plugin-cache/shenyu-plugin-cache-handler/src/main/java/org/apache/shenyu/plugin/cache/CachePlugin.java#L122) - [ApplicationConfigCache.init():42–49](https://github.com/apache/shenyu/blob/66d7d954ca37d651a5ad916f988a8081157a7ab4/shenyu-plugin/shenyu-plugin-cache/shenyu-plugin-cache-handler/src/main/java/org/apache/shenyu/plugin/cache/cache/ApplicationConfigCache.java#L42) - `CachePluginDataHandler` invalidates selector backends on configuration changes, making first-request initialization reachable again after updates. ### Reproduction / validation A probe compiled the current CachePlugin, ApplicationConfigCache and required cache helpers. It registered a small SPI backend whose builder used a barrier to hold two simultaneous first requests after their empty lookup; the backend only tracked creation/close calls and did not contact Redis. It invoked the actual private `getCache()` helper concurrently, then invalidated the selector: ```text LAZY_BUILDS=2 DIFFERENT_INSTANCES=true CLOSED_BEFORE_INVALIDATE=0 CLOSED_AFTER_INVALIDATE=1 CREATED=2 ``` The factory map owned only the winning instance; normal invalidation closed only that instance, leaving the overwritten backend unclosed. An independent reviewer confirmed the production lazy-init/update paths. No claim is made that a real Redis pool count was measured; RedisCache owns a factory that needs explicit cleanup, so the ownership loss is relevant for that backend. ### Impact / expected behavior Concurrent initial traffic and repeated selector updates can leak backend clients/pools and give simultaneous requests different supposedly selector-scoped caches. Each constructed backend should have a single tracked owner and a deterministic close path. ### Suggested fix Coordinate initialization atomically per selector and close any replaced/unused instance safely. Also audit `invalidateCache()`'s separate get/close/remove operations so an older invalidation cannot remove a concurrently installed replacement. Preserve in-flight request safety during handoff rather than simply closing arbitrary instances. ### Related existing work #7156 covers missing cleanup on Redis configuration replacement. #7163 covers plugin-global replacement ordering and handler removal. This issue is specifically request-driven per-selector get-then-init creating multiple owners for the same key. #3548 concerns a blocking Redis call on Reactor threads. None describes this reproduced per-selector initialization race. ### Reviewed revision Apache ShenYu 2.7.2-SNAPSHOT, `master@66d7d954ca37d651a5ad916f988a8081157a7ab4`. Severity Medium / P2; confidence high. Unit-test and CI issue categories excluded. -- 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]
