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()));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user