mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
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).
This commit is contained in:
@@ -104,4 +104,11 @@ public interface ServerCache {
|
||||
default void visit(MetricVisitor visitor) {
|
||||
// do nothing by default
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwrap the underlying ServerCache.
|
||||
*/
|
||||
default <T> T unwrap(Class<T> cls) {
|
||||
return (T) this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 class ServerCacheConfig {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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> T unwrap(Class<T> 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<Object, Object> getAll(Set<Object> keys) {
|
||||
Map<Object, Object> keyMapping = new HashMap<>(keys.size());
|
||||
keys.forEach(k -> keyMapping.put(key(k), k));
|
||||
Map<Object, Object> tmp = delegate.getAll(keyMapping.keySet());
|
||||
Map<Object, Object> 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<Object, Object> keyValues) {
|
||||
Map<Object, Object> tmp = new HashMap<>();
|
||||
keyValues.forEach((k, v) -> tmp.put(key(k), v));
|
||||
delegate.putAll(tmp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll(Set<Object> keys) {
|
||||
delegate.removeAll(keys.stream().map(this::key).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Object,Object> 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<Object, Object> 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<Object, Object> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-17
@@ -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 class DefaultServerCache implements ServerCache {
|
||||
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 @@ public class DefaultServerCache implements ServerCache {
|
||||
/**
|
||||
* Get the cache entry - override for query cache to validate dependent tables.
|
||||
*/
|
||||
protected CacheEntry getCacheEntry(Object id) {
|
||||
final SoftReference<CacheEntry> ref = map.get(key(id));
|
||||
protected CacheEntry getCacheEntry(Object key) {
|
||||
final SoftReference<CacheEntry> ref = map.get(key);
|
||||
return ref != null ? ref.get() : null;
|
||||
}
|
||||
|
||||
@@ -198,8 +189,7 @@ public class DefaultServerCache implements ServerCache {
|
||||
* 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 class DefaultServerCache implements ServerCache {
|
||||
* Remove an entry from the cache.
|
||||
*/
|
||||
@Override
|
||||
public void remove(Object id) {
|
||||
SoftReference<CacheEntry> entry = map.remove(key(id));
|
||||
public void remove(Object key) {
|
||||
SoftReference<CacheEntry> entry = map.remove(key);
|
||||
if (entry != null && entry.get() != null) {
|
||||
removeCount.increment();
|
||||
}
|
||||
|
||||
-5
@@ -3,7 +3,6 @@ package io.ebeaninternal.server.cache;
|
||||
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 final class DefaultServerCacheConfig {
|
||||
this.maxSize = options.getMaxSize();
|
||||
}
|
||||
|
||||
public CurrentTenantProvider getTenantProvider() {
|
||||
return config.getTenantProvider();
|
||||
}
|
||||
|
||||
public QueryCacheEntryValidate getQueryCacheEntryValidate() {
|
||||
return config.getQueryCacheEntryValidate();
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ final class DefaultServerCacheFactory implements ServerCacheFactory {
|
||||
if (executor != null) {
|
||||
cache.periodicTrim(executor);
|
||||
}
|
||||
return cache;
|
||||
return config.tenantAware(cache);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -27,8 +27,7 @@ public class DefaultServerQueryCache extends DefaultServerCache {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CacheEntry getCacheEntry(Object id) {
|
||||
Object key = key(id);
|
||||
protected CacheEntry getCacheEntry(Object key) {
|
||||
final SoftReference<CacheEntry> ref = map.get(key);
|
||||
CacheEntry entry = ref != null ? ref.get() : null;
|
||||
if (entry == null) {
|
||||
|
||||
@@ -48,7 +48,6 @@ final class DCountMetric implements CountMetric {
|
||||
|
||||
@Override
|
||||
public void visit(MetricVisitor visitor) {
|
||||
|
||||
long val = visitor.reset() ? count.sumThenReset() : count.sum();
|
||||
if (val > 0) {
|
||||
visitor.visitCount(new DCountMetricStats(name, val));
|
||||
|
||||
+14
-27
@@ -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 org.tests.model.basic.Customer;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
public class DefaultCacheHolderTest {
|
||||
class DefaultCacheHolderTest {
|
||||
|
||||
private final ThreadLocal<String> tenantId = new ThreadLocal<>();
|
||||
|
||||
@@ -25,42 +26,30 @@ public class DefaultCacheHolderTest {
|
||||
.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 class DefaultCacheHolderTest {
|
||||
}
|
||||
|
||||
@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 class DefaultCacheHolderTest {
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
|
||||
+41
-47
@@ -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 org.tests.model.basic.Customer;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class DefaultServerCacheManagerTest {
|
||||
class DefaultServerCacheManagerTest {
|
||||
|
||||
private final ThreadLocal<String> tenantId = new ThreadLocal<>();
|
||||
|
||||
@@ -29,7 +30,7 @@ public class DefaultServerCacheManagerTest {
|
||||
|
||||
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 class 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());
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ final class RedisCacheFactory implements ServerCacheFactory {
|
||||
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 @@ final class RedisCacheFactory implements ServerCacheFactory {
|
||||
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 @@ final class RedisCacheFactory implements ServerCacheFactory {
|
||||
cache.periodicTrim(executor);
|
||||
queryCaches.put(config.getCacheKey(), cache);
|
||||
}
|
||||
return cache;
|
||||
return config.tenantAware(cache);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
@@ -40,14 +40,14 @@ public class ClusterTest {
|
||||
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 class ClusterTest {
|
||||
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 class ClusterTest {
|
||||
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);
|
||||
|
||||
+1
-1
@@ -117,9 +117,9 @@ public class TestNatKeyCacheWithForeignKey extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void findSimple() {
|
||||
|
||||
setupData();
|
||||
clearAllL2Cache();
|
||||
appStats();
|
||||
|
||||
OCachedApp app0 = findAppByName("app0");
|
||||
assertThat(app0).isNotNull();
|
||||
|
||||
Reference in New Issue
Block a user