mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-11-06 00:32:18 +00:00
#1225 - ENH: Extend L2 server cache (near caching) for clearing "near caches"
This commit is contained in:
1 parent
69c045443c
commit
c7f4b56dd1
23 files changed
+585
-65
No files matched your search
@@ -0,0 +1,85 @@
|
||||
package io.ebeaninternal.server.cache;
|
||||
|
||||
import io.ebean.cache.ServerCacheFactory;
|
||||
import io.ebean.cache.ServerCacheOptions;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebeaninternal.server.cluster.ClusterManager;
|
||||
|
||||
/**
|
||||
* Configuration options when creating the default cache manager.
|
||||
*/
|
||||
public class CacheManagerOptions {
|
||||
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
private final ServerConfig serverConfig;
|
||||
|
||||
private final boolean localL2Caching;
|
||||
|
||||
private CurrentTenantProvider currentTenantProvider;
|
||||
|
||||
private ServerCacheFactory cacheFactory = new DefaultServerCacheFactory();
|
||||
private ServerCacheOptions beanDefault = new ServerCacheOptions();
|
||||
private ServerCacheOptions queryDefault = new ServerCacheOptions();
|
||||
|
||||
CacheManagerOptions() {
|
||||
this.localL2Caching = true;
|
||||
this.clusterManager = null;
|
||||
this.serverConfig = null;
|
||||
this.cacheFactory = new DefaultServerCacheFactory();
|
||||
this.beanDefault = new ServerCacheOptions();
|
||||
this.queryDefault = new ServerCacheOptions();
|
||||
}
|
||||
|
||||
public CacheManagerOptions(ClusterManager clusterManager, ServerConfig serverConfig, boolean localL2Caching) {
|
||||
this.clusterManager = clusterManager;
|
||||
this.serverConfig = serverConfig;
|
||||
this.localL2Caching = localL2Caching;
|
||||
this.currentTenantProvider = serverConfig.getCurrentTenantProvider();
|
||||
}
|
||||
|
||||
public CacheManagerOptions with(ServerCacheOptions beanDefault, ServerCacheOptions queryDefault) {
|
||||
this.beanDefault = beanDefault;
|
||||
this.queryDefault = queryDefault;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CacheManagerOptions with(ServerCacheFactory cacheFactory) {
|
||||
this.cacheFactory = cacheFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CacheManagerOptions with(CurrentTenantProvider currentTenantProvider) {
|
||||
this.currentTenantProvider = currentTenantProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getServerName() {
|
||||
return (serverConfig == null) ? "db" : serverConfig.getName();
|
||||
}
|
||||
|
||||
public boolean isLocalL2Caching() {
|
||||
return localL2Caching;
|
||||
}
|
||||
|
||||
public ServerCacheFactory getCacheFactory() {
|
||||
return cacheFactory;
|
||||
}
|
||||
|
||||
public ServerCacheOptions getBeanDefault() {
|
||||
return beanDefault;
|
||||
}
|
||||
|
||||
public ServerCacheOptions getQueryDefault() {
|
||||
return queryDefault;
|
||||
}
|
||||
|
||||
public CurrentTenantProvider getCurrentTenantProvider() {
|
||||
return currentTenantProvider;
|
||||
}
|
||||
|
||||
public ClusterManager getClusterManager() {
|
||||
return clusterManager;
|
||||
}
|
||||
}
|
||||
@@ -44,12 +44,21 @@ public class DefaultCacheAdapter implements ServerCacheManager {
|
||||
|
||||
@Override
|
||||
public void clear(Class<?> beanType) {
|
||||
cacheManager.getBeanCache(beanType).clear();
|
||||
cacheManager.getQueryCache(beanType).clear();
|
||||
cacheManager.clear(beanType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAll() {
|
||||
cacheManager.clearAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllLocal() {
|
||||
cacheManager.clearAllLocal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLocal(Class<?> beanType) {
|
||||
cacheManager.clearLocal(beanType);
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,24 @@ import io.ebean.cache.ServerCacheOptions;
|
||||
import io.ebean.cache.ServerCacheType;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
/**
|
||||
* Manages the construction of caches.
|
||||
*/
|
||||
class DefaultCacheHolder {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.ALL");
|
||||
|
||||
private final ConcurrentHashMap<String, ServerCache> allCaches = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentHashMap<String, Set<String>> collectIdCaches = new ConcurrentHashMap<>();
|
||||
|
||||
private final ServerCacheFactory cacheFactory;
|
||||
|
||||
private final ServerCacheOptions beanDefault;
|
||||
@@ -25,6 +33,10 @@ class DefaultCacheHolder {
|
||||
|
||||
private final CurrentTenantProvider tenantProvider;
|
||||
|
||||
DefaultCacheHolder(CacheManagerOptions builder) {
|
||||
this(builder.getCacheFactory(), builder.getBeanDefault(), builder.getQueryDefault(), builder.getCurrentTenantProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with a cache factory and default cache options.
|
||||
*
|
||||
@@ -42,7 +54,6 @@ class DefaultCacheHolder {
|
||||
ServerCache getCache(Class<?> beanType, String cacheKey, ServerCacheType type) {
|
||||
|
||||
return getCacheInternal(beanType, cacheKey, type);
|
||||
|
||||
}
|
||||
|
||||
private String key(String cacheKey, ServerCacheType type) {
|
||||
@@ -60,16 +71,43 @@ class DefaultCacheHolder {
|
||||
|
||||
private ServerCache createCache(Class<?> beanType, ServerCacheType type, String key) {
|
||||
ServerCacheOptions options = getCacheOptions(beanType, type);
|
||||
|
||||
if (type == ServerCacheType.COLLECTION_IDS) {
|
||||
synchronized (this) {
|
||||
collectIdCaches.computeIfAbsent(beanType.getName(), s -> new ConcurrentSkipListSet<>()).add(key);
|
||||
}
|
||||
}
|
||||
return cacheFactory.createCache(type, key, tenantProvider, options);
|
||||
}
|
||||
|
||||
void clearAll() {
|
||||
log.debug("clearAll");
|
||||
for (ServerCache serverCache : allCaches.values()) {
|
||||
serverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clear(String name) {
|
||||
log.debug("clear {}", name);
|
||||
clearIfExists(key(name, ServerCacheType.QUERY));
|
||||
clearIfExists(key(name, ServerCacheType.BEAN));
|
||||
clearIfExists(key(name, ServerCacheType.NATURAL_KEY));
|
||||
Set<String> keys = collectIdCaches.get(name);
|
||||
if (keys != null) {
|
||||
for (String collectionIdKey : keys) {
|
||||
clearIfExists(collectionIdKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearIfExists(String fullKey) {
|
||||
ServerCache cache = allCaches.get(fullKey);
|
||||
if (cache != null) {
|
||||
log.trace("clear cache {}", fullKey);
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache options for a given bean type.
|
||||
*/
|
||||
|
||||
+32
-8
@@ -1,34 +1,37 @@
|
||||
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;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebeaninternal.server.cluster.ClusterManager;
|
||||
|
||||
/**
|
||||
* Manages the bean and query caches.
|
||||
*/
|
||||
public class DefaultServerCacheManager implements SpiCacheManager {
|
||||
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
private final DefaultCacheHolder cacheHolder;
|
||||
|
||||
private final boolean localL2Caching;
|
||||
|
||||
private final String serverName;
|
||||
|
||||
/**
|
||||
* Create with a cache factory and default cache options.
|
||||
*/
|
||||
public DefaultServerCacheManager(boolean localL2Caching, CurrentTenantProvider tenantProvider, ServerCacheFactory cacheFactory,
|
||||
ServerCacheOptions beanDefault, ServerCacheOptions queryDefault) {
|
||||
this.localL2Caching = localL2Caching;
|
||||
this.cacheHolder = new DefaultCacheHolder(cacheFactory, beanDefault, queryDefault, tenantProvider);
|
||||
public DefaultServerCacheManager(CacheManagerOptions builder) {
|
||||
this.clusterManager = builder.getClusterManager();
|
||||
this.serverName = builder.getServerName();
|
||||
this.localL2Caching = builder.isLocalL2Caching();
|
||||
this.cacheHolder = new DefaultCacheHolder(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct when l2 cache is disabled.
|
||||
*/
|
||||
public DefaultServerCacheManager() {
|
||||
this(true, null, new DefaultServerCacheFactory(), new ServerCacheOptions(), new ServerCacheOptions());
|
||||
this(new CacheManagerOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,6 +45,27 @@ public class DefaultServerCacheManager implements SpiCacheManager {
|
||||
@Override
|
||||
public void clearAll() {
|
||||
cacheHolder.clearAll();
|
||||
if (clusterManager != null) {
|
||||
clusterManager.cacheClearAll(serverName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllLocal() {
|
||||
cacheHolder.clearAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(Class<?> beanType) {
|
||||
cacheHolder.clear(name(beanType));
|
||||
if (clusterManager != null) {
|
||||
clusterManager.cacheClear(serverName, beanType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLocal(Class<?> beanType) {
|
||||
cacheHolder.clear(name(beanType));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package io.ebeaninternal.server.cache;
|
||||
|
||||
import io.ebeaninternal.server.cluster.BinaryMessage;
|
||||
import io.ebeaninternal.server.cluster.BinaryMessageList;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Cache events broadcast across the cluster.
|
||||
*/
|
||||
public class RemoteCacheEvent {
|
||||
|
||||
private boolean clearAll;
|
||||
|
||||
private List<String> clearCaches;
|
||||
|
||||
/**
|
||||
* Clear all the caches.
|
||||
*/
|
||||
public RemoteCacheEvent(boolean clearAll) {
|
||||
this.clearAll = clearAll;
|
||||
this.clearCaches = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear caches for the given bean type.
|
||||
*/
|
||||
public RemoteCacheEvent(Class<?> beanType) {
|
||||
this.clearAll = false;
|
||||
this.clearCaches = new ArrayList<>(1);
|
||||
this.clearCaches.add(beanType.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with the read options.
|
||||
*/
|
||||
public RemoteCacheEvent(boolean clearAll, List<String> beanTypes) {
|
||||
this.clearAll = clearAll;
|
||||
this.clearCaches = beanTypes;
|
||||
}
|
||||
|
||||
public boolean isClearAll() {
|
||||
return clearAll;
|
||||
}
|
||||
|
||||
public List<String> getClearCaches() {
|
||||
return clearCaches;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "clearAll:" + clearAll + " caches:" + clearCaches;
|
||||
}
|
||||
|
||||
public static RemoteCacheEvent readBinaryMessage(DataInput dataInput) throws IOException {
|
||||
|
||||
boolean clearAll = dataInput.readBoolean();
|
||||
int size = dataInput.readInt();
|
||||
|
||||
List<String> clearCache = null;
|
||||
if (size > 0) {
|
||||
clearCache = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
clearCache.add(dataInput.readUTF());
|
||||
}
|
||||
}
|
||||
|
||||
return new RemoteCacheEvent(clearAll, clearCache);
|
||||
}
|
||||
|
||||
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
|
||||
|
||||
int bufferSize = (clearCaches == null) ? 0 : clearCaches.size() * 30;
|
||||
|
||||
BinaryMessage msg = new BinaryMessage(bufferSize + 10);
|
||||
DataOutputStream os = msg.getOs();
|
||||
os.writeInt(BinaryMessage.TYPE_CACHE);
|
||||
os.writeBoolean(clearAll);
|
||||
if (clearCaches == null) {
|
||||
os.writeInt(0);
|
||||
} else {
|
||||
os.writeInt(clearCaches.size());
|
||||
for (String cacheName : clearCaches) {
|
||||
os.writeUTF(cacheName);
|
||||
}
|
||||
}
|
||||
msgList.add(msg);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,24 @@ public interface SpiCacheManager {
|
||||
*/
|
||||
ServerCache getQueryCache(Class<?> beanType);
|
||||
|
||||
/**
|
||||
* Clear the caches for the given bean type.
|
||||
*/
|
||||
void clear(Class<?> beanType);
|
||||
|
||||
/**
|
||||
* Clear all the caches.
|
||||
*/
|
||||
void clearAll();
|
||||
|
||||
/**
|
||||
* Clear all local caches.
|
||||
*/
|
||||
void clearAllLocal();
|
||||
|
||||
/**
|
||||
* Clear local caches for the given bean type.
|
||||
*/
|
||||
void clearLocal(Class<?> beanType);
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user