]
Tristan Tarrant updated ISPN-10171:
-----------------------------------
Status: Pull Request Sent (was: Open)
Spring Cache sync locking does not work
---------------------------------------
Key: ISPN-10171
URL:
https://issues.jboss.org/browse/ISPN-10171
Project: Infinispan
Issue Type: Bug
Components: Spring Integration
Affects Versions: 9.4.11.Final, 10.0.0.Beta4
Environment: > mvn -version
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-24T20:41:47+02:00)
Maven home: /usr/local/Cellar/maven/3.6.0/libexec
Java version: 11.0.1, vendor: Oracle Corporation, runtime:
/Library/Java/JavaVirtualMachines/openjdk-11.0.1.jdk/Contents/Home
Default locale: en_NL, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.4", arch: "x86_64",
family: "mac"
Reporter: Rens van Leeuwen
Assignee: Katia Aresti
Priority: Major
With
ISPN-7224/https://github.com/infinispan/infinispan/pull/5262, an implementation was
written to support a synchronous get that implements Spring Cache's {{@Cacheable(sync
= true)}}.
That seems to work well in isolation, but not in an integrated way. By that I mean, that
the implementation of {{SpringCache}} maintains its own {{ReentrantLock}}s in each
instance.
Zooming out a bit, this is part of the call stack when the {{SpringCache}} instance is
looked up during handling the {{@Cacheable(sync = true)}} annotation:
{noformat}
CacheInterceptor.invoke(MethodInvocation) (org.springframework.cache.interceptor)
CacheAspectSupport.execute(CacheOperationInvoker, Object, Method, Object[])
(org.springframework.cache.interceptor)
CacheOperationContexts in CacheAspectSupport.CacheOperationContexts(Collection<?
extends CacheOperation>, Method, Object[], Object, Class<?>)
(org.springframework.cache.interceptor)
CacheAspectSupport.getOperationContext(CacheOperation, Method, Object[], Object,
Class<?>) (org.springframework.cache.interceptor)
CacheOperationContext in
CacheAspectSupport.CacheOperationContext(CacheOperationMetadata, Object[], Object)
(org.springframework.cache.interceptor)
CacheAspectSupport.getCaches(CacheOperationInvocationContext<CacheOperation>,
CacheResolver) (org.springframework.cache.interceptor)
AbstractCacheResolver.resolveCaches(CacheOperationInvocationContext<?>)
(org.springframework.cache.interceptor)
----->> SpringEmbeddedCacheManager.getCache(String)
(org.infinispan.spring.embedded.provider)
SpringCache.SpringCache(BasicCache)
(org.infinispan.spring.common.provider)
SpringCache.SpringCache(BasicCache, long, long)
(org.infinispan.spring.common.provider)
{noformat}
The problem with this is, that for each turn the interceptor handles the request a *new
instance* of the {{SpringCache}} is made in the {{SpringEmbeddedCacheManager}}, rendering
the use of the {{ReentrantLock}} mechanism useless to a certain extent, because multiple
threads accessing the {{@Cacheable(sync = true)}} method will each have their own
{{SpringCache}} and corresponding {{ReentrantLock}}.
In turn, there is no locking at all, and each thread will be executing the (assumed to
be) expensive code that is intended to be cached.
--
I'm intending to write a patch for this, but this would be the first time I commit to
an open source project (bear with me ;)). I'll try to provide a pull request for this.