Skip to content

fix: drop CallContext from the endpoint-mapping and FX rate cache keys - #2891

Closed
hongwei1 wants to merge 1 commit into
OpenBankProject:developfrom
hongwei1:feature/cache-key-drop-callcontext
Closed

fix: drop CallContext from the endpoint-mapping and FX rate cache keys#2891
hongwei1 wants to merge 1 commit into
OpenBankProject:developfrom
hongwei1:feature/cache-key-drop-callcontext

Conversation

@hongwei1

Copy link
Copy Markdown
Contributor

CacheKeyFromArguments renders every parameter that is not annotated @CacheKeyOmit. CallContext carries per-request state (startTime, correlationId, url, verb, ipAddress, user), so both keys were unique per request: the cache could never hit, and getCurrentFxRateCached wrote a fresh Redis entry per call that lived out its TTL.

getEndpointMappings additionally cached the (mappings, callContext) tuple. chill/Kryo cannot encode the lambda reachable through CallContext.resourceDocument, so every write failed and cachePut swallowed it as "result served uncached" - endpointMapping.cache.ttl.seconds bought nothing but a WARN per call. A hit would also have handed the caller the originating request's CallContext.

Split the memoized half into getEndpointMappingsCached(bankId) rather than annotating callContext on the caller: CacheKeyFromArguments reads the parameters of the method whose body ends in buildCacheKey, so binding the result to a val first leaves it with no parameters and it emits Nil.mkString("_") - an empty argument segment, i.e. every bankId sharing one entry. Verified with javap that the key now renders bankId :: Nil, and that getCurrentFxRateCached renders bankId :: from :: to :: Nil.

Add invalidateEndpointMappingCache() on create/update/delete, mirroring invalidateMethodRoutingCache: while callContext was in the key nothing could hit, so a stale entry was unreachable by construction; now that the cache works, writes have to publish themselves.

CacheKeyFromArguments renders every parameter that is not annotated
@CacheKeyOmit. CallContext carries per-request state (startTime,
correlationId, url, verb, ipAddress, user), so both keys were unique per
request: the cache could never hit, and getCurrentFxRateCached wrote a fresh
Redis entry per call that lived out its TTL.

getEndpointMappings additionally cached the (mappings, callContext) tuple.
chill/Kryo cannot encode the lambda reachable through
CallContext.resourceDocument, so every write failed and cachePut swallowed it
as "result served uncached" - endpointMapping.cache.ttl.seconds bought nothing
but a WARN per call. A hit would also have handed the caller the originating
request's CallContext.

Split the memoized half into getEndpointMappingsCached(bankId) rather than
annotating callContext on the caller: CacheKeyFromArguments reads the
parameters of the method whose body ends in buildCacheKey, so binding the
result to a val first leaves it with no parameters and it emits
Nil.mkString("_") - an empty argument segment, i.e. every bankId sharing one
entry. Verified with javap that the key now renders bankId :: Nil, and that
getCurrentFxRateCached renders bankId :: from :: to :: Nil.

Add invalidateEndpointMappingCache() on create/update/delete, mirroring
invalidateMethodRoutingCache: while callContext was in the key nothing could
hit, so a stale entry was unreachable by construction; now that the cache
works, writes have to publish themselves.
@sonarqubecloud

Copy link
Copy Markdown

@hongwei1 hongwei1 closed this Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant