From f5a779e18bdcef1cae70377e4602a2ef4ae8d3b4 Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Thu, 7 Apr 2022 15:26:21 +1200 Subject: [PATCH] Refactor L2 cache tenant awareness - add TenantAwareCache The design change is to use TenantAwareCache to deal with wrap/unwrap of tenant aware keys, removing any tenant awareness from the underlying cache implementations (DefaultServerCache, redis, hazelcast etc). --- .../main/java/io/ebean/cache/ServerCache.java | 7 + .../io/ebean/cache/ServerCacheConfig.java | 9 ++ .../java/io/ebean/cache/TenantAwareCache.java | 104 +++++++++++++++ .../io/ebean/cache/TenantAwareCacheTest.java | 122 ++++++++++++++++++ .../server/cache/DefaultServerCache.java | 24 +--- .../cache/DefaultServerCacheConfig.java | 5 - .../cache/DefaultServerCacheFactory.java | 2 +- .../server/cache/DefaultServerQueryCache.java | 3 +- .../server/profile/DCountMetric.java | 1 - .../server/cache/DefaultCacheHolderTest.java | 41 ++---- .../cache/DefaultServerCacheManagerTest.java | 88 ++++++------- .../io/ebean/redis/RedisCacheFactory.java | 6 +- .../java/org/integration/ClusterTest.java | 8 +- .../cache/TestNatKeyCacheWithForeignKey.java | 2 +- 14 files changed, 314 insertions(+), 108 deletions(-) create mode 100644 ebean-api/src/main/java/io/ebean/cache/TenantAwareCache.java create mode 100644 ebean-api/src/test/java/io/ebean/cache/TenantAwareCacheTest.java diff --git a/ebean-api/src/main/java/io/ebean/cache/ServerCache.java b/ebean-api/src/main/java/io/ebean/cache/ServerCache.java index 1476e567d8..c7c9b413ea 100644 --- a/ebean-api/src/main/java/io/ebean/cache/ServerCache.java +++ b/ebean-api/src/main/java/io/ebean/cache/ServerCache.java @@ -104,4 +104,11 @@ default ServerCacheStatistics statistics(boolean reset) { default void visit(MetricVisitor visitor) { // do nothing by default } + + /** + * Unwrap the underlying ServerCache. + */ + default T unwrap(Class cls) { + return (T) this; + } } diff --git a/ebean-api/src/main/java/io/ebean/cache/ServerCacheConfig.java b/ebean-api/src/main/java/io/ebean/cache/ServerCacheConfig.java index f5e4292992..80ffe471aa 100644 --- a/ebean-api/src/main/java/io/ebean/cache/ServerCacheConfig.java +++ b/ebean-api/src/main/java/io/ebean/cache/ServerCacheConfig.java @@ -13,6 +13,7 @@ public class ServerCacheConfig { private final ServerCacheOptions cacheOptions; private final CurrentTenantProvider tenantProvider; private final QueryCacheEntryValidate queryCacheEntryValidate; + private final TenantAwareKey tenantAwareKey; public ServerCacheConfig(ServerCacheType type, String cacheKey, String shortName, ServerCacheOptions cacheOptions, CurrentTenantProvider tenantProvider, QueryCacheEntryValidate queryCacheEntryValidate) { this.type = type; @@ -21,6 +22,14 @@ public ServerCacheConfig(ServerCacheType type, String cacheKey, String shortName this.cacheOptions = cacheOptions; this.tenantProvider = tenantProvider; this.queryCacheEntryValidate = queryCacheEntryValidate; + this.tenantAwareKey = (tenantProvider == null) ? null : new TenantAwareKey(tenantProvider); + } + + /** + * Return the ServerCache taking into account if multi-tenant is used. + */ + public ServerCache tenantAware(ServerCache cache) { + return tenantAwareKey == null ? cache : new TenantAwareCache(cache, tenantAwareKey); } /** diff --git a/ebean-api/src/main/java/io/ebean/cache/TenantAwareCache.java b/ebean-api/src/main/java/io/ebean/cache/TenantAwareCache.java new file mode 100644 index 0000000000..1a4e2f3d06 --- /dev/null +++ b/ebean-api/src/main/java/io/ebean/cache/TenantAwareCache.java @@ -0,0 +1,104 @@ +package io.ebean.cache; + +import io.ebean.meta.MetricVisitor; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * A ServerCache proxy that is tenant aware. + */ +public final class TenantAwareCache implements ServerCache { + + private final ServerCache delegate; + private final TenantAwareKey tenantAwareKey; + + /** + * Create given the TenantAwareKey and delegate cache to proxy to. + * + * @param delegate The cache to proxy to + * @param tenantAwareKey Provides tenant aware keys to use in the cache + */ + public TenantAwareCache(ServerCache delegate, TenantAwareKey tenantAwareKey) { + this.delegate = delegate; + this.tenantAwareKey = tenantAwareKey; + } + + /** + * Return the underlying ServerCache that is being delegated to. + */ + @Override + public T unwrap(Class cls) { + return (T)delegate; + } + + @Override + public void visit(MetricVisitor visitor) { + delegate.visit(visitor); + } + + private Object key(Object key) { + return tenantAwareKey.key(key); + } + + @Override + public Object get(Object id) { + return delegate.get(key(id)); + } + + @Override + public void put(Object id, Object value) { + delegate.put(key(id), value); + } + + @Override + public void remove(Object id) { + delegate.remove(key(id)); + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public int getHitRatio() { + return delegate.getHitRatio(); + } + + @Override + public ServerCacheStatistics getStatistics(boolean reset) { + return delegate.getStatistics(reset); + } + + @Override + public Map getAll(Set keys) { + Map keyMapping = new HashMap<>(keys.size()); + keys.forEach(k -> keyMapping.put(key(k), k)); + Map tmp = delegate.getAll(keyMapping.keySet()); + Map ret = new HashMap<>(keys.size()); + // unwrap tenant info here + tmp.forEach((k,v)-> ret.put(((TenantAwareKey.CacheKey) k).key, v)); + return ret; + } + + @Override + public void putAll(Map keyValues) { + Map tmp = new HashMap<>(); + keyValues.forEach((k, v) -> tmp.put(key(k), v)); + delegate.putAll(tmp); + } + + @Override + public void removeAll(Set keys) { + delegate.removeAll(keys.stream().map(this::key).collect(Collectors.toSet())); + } + +} diff --git a/ebean-api/src/test/java/io/ebean/cache/TenantAwareCacheTest.java b/ebean-api/src/test/java/io/ebean/cache/TenantAwareCacheTest.java new file mode 100644 index 0000000000..6d8bdd92c2 --- /dev/null +++ b/ebean-api/src/test/java/io/ebean/cache/TenantAwareCacheTest.java @@ -0,0 +1,122 @@ +package io.ebean.cache; + +import io.ebean.cache.TenantAwareKey.CacheKey; +import io.ebean.config.CurrentTenantProvider; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static org.assertj.core.api.Assertions.assertThat; + +class TenantAwareCacheTest { + + ServerCache serverCache; + TenantAwareCache cache; + + TenantAwareCacheTest() { + TenantAwareKey key = new TenantAwareKey(new TenantProv()); + this.serverCache = new Cache(); + this.cache = new TenantAwareCache(serverCache, key); + } + + @Test + void put_get_remove() { + cache.put("A", "a"); + Object val = cache.get("A"); + assertThat(val).isEqualTo("a"); + + CacheKey cacheKey = new CacheKey("A", 42); + Object val2 = serverCache.get(cacheKey); + assertThat(val2).isEqualTo("a"); + + cache.put("B", "bb"); + assertThat(cache.size()).isEqualTo(2); + cache.remove("A"); + assertThat(cache.get("A")).isNull(); + assertThat(cache.size()).isEqualTo(1); + + cache.clear(); + assertThat(cache.size()).isEqualTo(0); + assertThat(cache.get("B")).isNull(); + } + + @Test + void putAll_getAll_removeAll() { + Map map = new HashMap<>(); + map.put("A", "a"); + map.put("B", "b"); + map.put("C", "c"); + + cache.putAll(map); + assertThat(cache.size()).isEqualTo(3); + assertThat(cache.get("A")).isEqualTo("a"); + assertThat(serverCache.get(new CacheKey("A", 42))).isEqualTo("a"); + + + Map result = cache.getAll(Set.of("A", "B", "C", "D")); + assertThat(result).hasSize(3); + assertThat(result).containsOnlyKeys("A", "B", "C"); + assertThat(result.values()).containsOnly("a", "b", "c"); + + cache.removeAll(Set.of("A", "C", "D")); + assertThat(cache.size()).isEqualTo(1); + + assertThat(cache.get("B")).isEqualTo("b"); + assertThat(serverCache.get(new CacheKey("B", 42))).isEqualTo("b"); + + cache.remove("B"); + assertThat(cache.size()).isEqualTo(0); + } + + + static class TenantProv implements CurrentTenantProvider { + + @Override + public Object currentId() { + return 42; + } + } + + static class Cache implements ServerCache { + + Map map = new ConcurrentHashMap<>(); + + @Override + public Object get(Object id) { + return map.get(id); + } + + @Override + public void put(Object id, Object value) { + map.put(id, value); + } + + @Override + public void remove(Object id) { + map.remove(id); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public int getHitRatio() { + return 0; + } + + @Override + public ServerCacheStatistics getStatistics(boolean reset) { + return null; + } + } +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java b/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java index ebd0861179..925b8b0fec 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java @@ -52,14 +52,12 @@ public class DefaultServerCache implements ServerCache { private final int trimFrequency; private final int maxIdleSecs; private final int maxSecsToLive; - private final TenantAwareKey tenantAwareKey; public DefaultServerCache(DefaultServerCacheConfig config) { this.name = config.getName(); this.shortName = config.getShortName(); this.map = config.getMap(); this.maxSize = config.getMaxSize(); - this.tenantAwareKey = new TenantAwareKey(config.getTenantProvider()); this.maxIdleSecs = config.getMaxIdleSecs(); this.maxSecsToLive = config.getMaxSecsToLive(); this.trimFrequency = config.determineTrimFrequency(); @@ -152,19 +150,12 @@ public void clear() { map.clear(); } - /** - * Return the tenant aware key. - */ - protected Object key(Object id) { - return tenantAwareKey.key(id); - } - /** * Return a value from the cache. */ @Override - public Object get(Object id) { - CacheEntry entry = getCacheEntry(id); + public Object get(Object key) { + CacheEntry entry = getCacheEntry(key); if (entry == null) { missCount.increment(); return null; @@ -184,8 +175,8 @@ protected Object unwrapEntry(CacheEntry entry) { /** * Get the cache entry - override for query cache to validate dependent tables. */ - protected CacheEntry getCacheEntry(Object id) { - final SoftReference ref = map.get(key(id)); + protected CacheEntry getCacheEntry(Object key) { + final SoftReference ref = map.get(key); return ref != null ? ref.get() : null; } @@ -198,8 +189,7 @@ public void putAll(Map keyValues) { * Put a value into the cache. */ @Override - public void put(Object id, Object value) { - Object key = key(id); + public void put(Object key, Object value) { map.put(key, new SoftReference<>(new CacheEntry(key, value))); putCount.increment(); } @@ -208,8 +198,8 @@ public void put(Object id, Object value) { * Remove an entry from the cache. */ @Override - public void remove(Object id) { - SoftReference entry = map.remove(key(id)); + public void remove(Object key) { + SoftReference entry = map.remove(key); if (entry != null && entry.get() != null) { removeCount.increment(); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheConfig.java b/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheConfig.java index 2c329a62aa..2e5c5dbcd6 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheConfig.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheConfig.java @@ -3,7 +3,6 @@ import io.ebean.cache.QueryCacheEntryValidate; import io.ebean.cache.ServerCacheConfig; import io.ebean.cache.ServerCacheOptions; -import io.ebean.config.CurrentTenantProvider; import io.ebeaninternal.server.cache.DefaultServerCache.CacheEntry; import java.lang.ref.SoftReference; @@ -34,10 +33,6 @@ public DefaultServerCacheConfig(ServerCacheConfig config, Map ref = map.get(key); CacheEntry entry = ref != null ? ref.get() : null; if (entry == null) { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DCountMetric.java b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DCountMetric.java index ba74a5e651..962c6ce226 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DCountMetric.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DCountMetric.java @@ -48,7 +48,6 @@ public long get(boolean reset) { @Override public void visit(MetricVisitor visitor) { - long val = visitor.reset() ? count.sumThenReset() : count.sum(); if (val > 0) { visitor.visitCount(new DCountMetricStats(name, val)); diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultCacheHolderTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultCacheHolderTest.java index 3a61f60ee6..565d41d766 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultCacheHolderTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultCacheHolderTest.java @@ -1,5 +1,6 @@ package io.ebeaninternal.server.cache; +import io.ebean.cache.ServerCache; import io.ebean.cache.ServerCacheFactory; import io.ebean.cache.ServerCacheOptions; import io.ebean.cache.ServerCacheType; @@ -12,7 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat; -public class DefaultCacheHolderTest { +class DefaultCacheHolderTest { private final ThreadLocal tenantId = new ThreadLocal<>(); @@ -25,42 +26,30 @@ private CacheManagerOptions options() { .with(cacheFactory, new TableModState()); } - @Test - public void getCache_normal() { - + void getCache_normal() { DefaultCacheHolder holder = new DefaultCacheHolder(options()); - DefaultServerCache cache = cache(holder, Customer.class); - assertThat(cache.getName()).isEqualTo("org.tests.model.basic.Customer_B"); - assertThat(cache.getShortName()).isEqualTo("Customer_B"); - - DefaultServerCache cache1 = cache(holder, Customer.class); + ServerCache cache = cache(holder, Customer.class); + ServerCache cache1 = cache(holder, Customer.class); assertThat(cache1).isSameAs(cache); - DefaultServerCache cache2 = cache(holder, Contact.class); + ServerCache cache2 = cache(holder, Contact.class); assertThat(cache1).isNotSameAs(cache2); - assertThat(cache2.getName()).isEqualTo("org.tests.model.basic.Contact_B"); - assertThat(cache2.getShortName()).isEqualTo("Contact_B"); - } - private DefaultServerCache cache(DefaultCacheHolder holder, Class type) { - return (DefaultServerCache) holder.getCache(type, ServerCacheType.BEAN); + private ServerCache cache(DefaultCacheHolder holder, Class type) { + return holder.getCache(type, ServerCacheType.BEAN); } @Test - public void getCache_multiTenant() throws Exception { - + void getCache_multiTenant() throws Exception { CacheManagerOptions builder = options().with(tenantId::get); DefaultCacheHolder holder = new DefaultCacheHolder(builder); tenantId.set("ten_1"); - DefaultServerCache cache = cache(holder, Customer.class); - assertThat(cache.getName()).isEqualTo("org.tests.model.basic.Customer_B"); - assertThat(cache.getShortName()).isEqualTo("Customer_B"); - + ServerCache cache = cache(holder, Customer.class); cache.put("1", "value-for-tenant1"); cache.put("2", "an other value-for-tenant1"); @@ -109,10 +98,9 @@ public void getCache_multiTenant() throws Exception { } @Test - public void clearAll() { - + void clearAll() { DefaultCacheHolder holder = new DefaultCacheHolder(options()); - DefaultServerCache cache = cache(holder, Customer.class); + ServerCache cache = cache(holder, Customer.class); cache.put("foo", "foo"); assertThat(cache.size()).isEqualTo(1); holder.clearAll(); @@ -121,12 +109,11 @@ public void clearAll() { } @Test - public void clearAll_multiTenant() { - + void clearAll_multiTenant() { CacheManagerOptions options = options().with(tenantId::get); DefaultCacheHolder holder = new DefaultCacheHolder(options); - DefaultServerCache cache = cache(holder, Customer.class); + ServerCache cache = cache(holder, Customer.class); cache.put("foo", "foo"); assertThat(cache.size()).isEqualTo(1); diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultServerCacheManagerTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultServerCacheManagerTest.java index b689d9e500..8d9a3b51c2 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultServerCacheManagerTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/cache/DefaultServerCacheManagerTest.java @@ -1,5 +1,6 @@ package io.ebeaninternal.server.cache; +import io.ebean.cache.ServerCache; import io.ebean.config.ContainerConfig; import io.ebean.config.CurrentTenantProvider; import io.ebean.config.DatabaseConfig; @@ -11,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; -public class DefaultServerCacheManagerTest { +class DefaultServerCacheManagerTest { private final ThreadLocal tenantId = new ThreadLocal<>(); @@ -29,7 +30,7 @@ public Object currentId() { private final DefaultServerCacheManager multiTenantManager; - public DefaultServerCacheManagerTest(){ + DefaultServerCacheManagerTest(){ CacheManagerOptions builder = new CacheManagerOptions(clusterManager, new DatabaseConfig(), true); builder.with(new TdTenPro()); this.multiTenantManager = new DefaultServerCacheManager(builder); @@ -37,86 +38,79 @@ public DefaultServerCacheManagerTest(){ @Test - public void getCache_normal() { + void getCache_normal() { + ServerCache cache = cache(manager, Customer.class); + DefaultServerCache dsc = cache.unwrap(DefaultServerCache.class); + assertThat(dsc.getName()).isEqualTo("org.tests.model.basic.Customer_B"); + assertThat(dsc.getShortName()).isEqualTo("Customer_B"); - DefaultServerCache cache = cache(manager, Customer.class); - assertThat(cache.getName()).isEqualTo("org.tests.model.basic.Customer_B"); - assertThat(cache.getShortName()).isEqualTo("Customer_B"); - - DefaultServerCache cache1 = cache(manager, Customer.class); + ServerCache cache1 = cache(manager, Customer.class); assertThat(cache1).isSameAs(cache); - DefaultServerCache cache2 = cache(manager, Contact.class); + ServerCache cache2 = cache(manager, Contact.class); assertThat(cache1).isNotSameAs(cache2); - assertThat(cache2.getName()).isEqualTo("org.tests.model.basic.Contact_B"); - assertThat(cache2.getShortName()).isEqualTo("Contact_B"); + DefaultServerCache dsc2 = cache2.unwrap(DefaultServerCache.class); + assertThat(dsc2.getName()).isEqualTo("org.tests.model.basic.Contact_B"); + assertThat(dsc2.getShortName()).isEqualTo("Contact_B"); - DefaultServerCache natKeyCache = (DefaultServerCache) manager.getNaturalKeyCache(Customer.class); - assertThat(natKeyCache.getName()).isEqualTo("org.tests.model.basic.Customer_N"); - assertThat(natKeyCache.getShortName()).isEqualTo("Customer_N"); + ServerCache natKeyCache = manager.getNaturalKeyCache(Customer.class); + DefaultServerCache dscNatKey = natKeyCache.unwrap(DefaultServerCache.class); + assertThat(dscNatKey.getName()).isEqualTo("org.tests.model.basic.Customer_N"); + assertThat(dscNatKey.getShortName()).isEqualTo("Customer_N"); - DefaultServerCache queryCache = (DefaultServerCache) manager.getQueryCache(Customer.class); - assertThat(queryCache.getName()).isEqualTo("org.tests.model.basic.Customer_Q"); - assertThat(queryCache.getShortName()).isEqualTo("Customer_Q"); + ServerCache queryCache = manager.getQueryCache(Customer.class); + DefaultServerCache dscQueryCache = queryCache.unwrap(DefaultServerCache.class); + assertThat(dscQueryCache.getName()).isEqualTo("org.tests.model.basic.Customer_Q"); + assertThat(dscQueryCache.getShortName()).isEqualTo("Customer_Q"); - DefaultServerCache collCache = (DefaultServerCache) manager.getCollectionIdsCache(Customer.class, "contacts"); - assertThat(collCache.getName()).isEqualTo("org.tests.model.basic.Customer.contacts_C"); - assertThat(collCache.getShortName()).isEqualTo("Customer.contacts_C"); + ServerCache collCache = manager.getCollectionIdsCache(Customer.class, "contacts"); + DefaultServerCache dscCollCache = collCache.unwrap(DefaultServerCache.class); + assertThat(dscCollCache.getName()).isEqualTo("org.tests.model.basic.Customer.contacts_C"); + assertThat(dscCollCache.getShortName()).isEqualTo("Customer.contacts_C"); - cache.clearCount.reset(); - collCache.clearCount.reset(); - queryCache.clearCount.reset(); - natKeyCache.clearCount.reset(); + cache.statistics(true); + collCache.statistics(true); + queryCache.statistics(true); + natKeyCache.statistics(true); manager.clear(Customer.class); - assertThat(cache.clearCount.get(true)).isEqualTo(1); - assertThat(natKeyCache.clearCount.get(true)).isEqualTo(1); - assertThat(queryCache.clearCount.get(true)).isEqualTo(1); - assertThat(collCache.clearCount.get(true)).isEqualTo(1); + assertThat(cache.statistics(true).getClearCount()).isEqualTo(1); + assertThat(natKeyCache.statistics(true).getClearCount()).isEqualTo(1); + assertThat(queryCache.statistics(true).getClearCount()).isEqualTo(1); + assertThat(collCache.statistics(true).getClearCount()).isEqualTo(1); } - private DefaultServerCache cache(DefaultServerCacheManager manager, Class beanType) { - return (DefaultServerCache) manager.getBeanCache(beanType); + private ServerCache cache(DefaultServerCacheManager manager, Class beanType) { + return manager.getBeanCache(beanType); } @Test - public void getCache_multiTenant() { - + void getCache_multiTenant() { tenantId.set("ten1"); - DefaultServerCache cache = cache(multiTenantManager, Customer.class); - assertThat(cache.getName()).isEqualTo("org.tests.model.basic.Customer_B"); + ServerCache cache = cache(multiTenantManager, Customer.class); cache.put("1", "tenant1"); tenantId.set("ten2"); - assertThat(cache.get("1")).isNull(); tenantId.set("ten1"); - - assertThat(cache.get("1")).isNotNull(); - + assertThat(cache.get("1")).isEqualTo("tenant1"); } @Test - public void getCache_singleTenant() { - + void getCache_singleTenant() { + ServerCache cache = cache(manager, Customer.class); tenantId.set("ten1"); - DefaultServerCache cache = cache(manager, Customer.class); - assertThat(cache.getName()).isEqualTo("org.tests.model.basic.Customer_B"); - cache.put("1", "tenant1"); tenantId.set("ten2"); - assertThat(cache.get("1")).isEqualTo("tenant1"); - } @Test - public void isLocalL2Caching() { - + void isLocalL2Caching() { assertTrue(manager.isLocalL2Caching()); assertTrue(multiTenantManager.isLocalL2Caching()); } diff --git a/ebean-redis/src/main/java/io/ebean/redis/RedisCacheFactory.java b/ebean-redis/src/main/java/io/ebean/redis/RedisCacheFactory.java index cbd5628550..3b08ef21f9 100644 --- a/ebean-redis/src/main/java/io/ebean/redis/RedisCacheFactory.java +++ b/ebean-redis/src/main/java/io/ebean/redis/RedisCacheFactory.java @@ -139,7 +139,7 @@ private ServerCache createNormalCache(ServerCacheConfig config) { RedisCache redisCache = createRedisCache(config); boolean nearCache = config.getCacheOptions().isNearCache(); if (!nearCache) { - return redisCache; + return config.tenantAware(redisCache); } String cacheKey = config.getCacheKey(); @@ -147,7 +147,7 @@ private ServerCache createNormalCache(ServerCacheConfig config) { near.periodicTrim(executor); DuelCache duelCache = new DuelCache(near, redisCache, cacheKey, nearCacheNotify); nearCacheMap.put(cacheKey, duelCache); - return duelCache; + return config.tenantAware(duelCache); } private RedisCache createRedisCache(ServerCacheConfig config) { @@ -173,7 +173,7 @@ private ServerCache createQueryCache(ServerCacheConfig config) { cache.periodicTrim(executor); queryCaches.put(config.getCacheKey(), cache); } - return cache; + return config.tenantAware(cache); } finally { lock.unlock(); } diff --git a/ebean-redis/src/test/java/org/integration/ClusterTest.java b/ebean-redis/src/test/java/org/integration/ClusterTest.java index 16b193dee3..f52466c0b1 100644 --- a/ebean-redis/src/test/java/org/integration/ClusterTest.java +++ b/ebean-redis/src/test/java/org/integration/ClusterTest.java @@ -40,14 +40,14 @@ public void testBothNear() throws InterruptedException { foo.save(); DB.cacheManager().clearAll(); - DB.getDefault().metaInfo().resetAllMetrics(); + db.metaInfo().resetAllMetrics(); other.metaInfo().resetAllMetrics(); Person fooA = DB.find(Person.class, foo.getId()); allowAsyncMessaging(); // allow time for background cache load Person fooB = other.find(Person.class, foo.getId()); - DuelCache dualCacheA = (DuelCache) DB.cacheManager().beanCache(Person.class); + DuelCache dualCacheA = db.cacheManager().beanCache(Person.class).unwrap(DuelCache.class); assertCounts(dualCacheA, 0, 1, 0, 1); fooA = DB.find(Person.class, foo.getId()); assertCounts(dualCacheA, 1, 1, 0, 1); @@ -55,7 +55,7 @@ public void testBothNear() throws InterruptedException { fooA = DB.find(Person.class, foo.getId()); assertCounts(dualCacheA, 2, 1, 0, 1); fooB = other.find(Person.class, foo.getId()); - DuelCache dualCacheB = (DuelCache) other.cacheManager().beanCache(Person.class); + DuelCache dualCacheB = other.cacheManager().beanCache(Person.class).unwrap(DuelCache.class); assertCounts(dualCacheB, 2, 1, 1, 0); } @@ -73,7 +73,7 @@ public void test() throws InterruptedException { other.cacheManager().clearAll(); other.metaInfo().resetAllMetrics(); - DuelCache dualCache = (DuelCache) other.cacheManager().beanCache(Person.class); + DuelCache dualCache = other.cacheManager().beanCache(Person.class).unwrap(DuelCache.class); Person foo0 = other.find(Person.class, 1); assertCounts(dualCache, 0, 1, 0, 1); diff --git a/ebean-test/src/test/java/org/tests/model/basic/cache/TestNatKeyCacheWithForeignKey.java b/ebean-test/src/test/java/org/tests/model/basic/cache/TestNatKeyCacheWithForeignKey.java index 6e73f72c42..c08edb848f 100644 --- a/ebean-test/src/test/java/org/tests/model/basic/cache/TestNatKeyCacheWithForeignKey.java +++ b/ebean-test/src/test/java/org/tests/model/basic/cache/TestNatKeyCacheWithForeignKey.java @@ -117,9 +117,9 @@ private List findListApps(String detail, OCachedApp... apps) { @Test public void findSimple() { - setupData(); clearAllL2Cache(); + appStats(); OCachedApp app0 = findAppByName("app0"); assertThat(app0).isNotNull();