#1427 - QueryCache should be cleared, if one of a dependent bean is updated

Propagation across cluster.
This commit is contained in:
rob bygrave committed 2018-06-16 00:09:03 +12:00
1 parent 96cc8d7605
commit 6a9ab49ef0
10 files changed
+133 -12

No files matched your search

@@ -22,7 +22,7 @@ import java.util.Set;
* This includes Cluster notification, and BeanPersistListeners.
* </p>
*/
public final class PostCommitProcessing {
final class PostCommitProcessing {
private static final Logger logger = LoggerFactory.getLogger(PostCommitProcessing.class);
@@ -51,7 +51,7 @@ public final class PostCommitProcessing {
/**
* Create for an external modification.
*/
public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) {
PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) {
this.clusterManager = clusterManager;
this.manager = manager;
@@ -68,7 +68,7 @@ public final class PostCommitProcessing {
/**
* Create for a transaction.
*/
public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, SpiTransaction transaction) {
PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, SpiTransaction transaction) {
this.clusterManager = clusterManager;
this.manager = manager;
@@ -2,6 +2,10 @@ package io.ebeaninternal.server.transaction;
import io.ebean.cache.QueryCacheEntry;
import io.ebean.cache.QueryCacheEntryValidate;
import io.ebean.cache.ServerCacheNotification;
import io.ebean.cache.ServerCacheNotify;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Set;
@@ -13,24 +17,28 @@ import java.util.concurrent.ConcurrentHashMap;
* This information is used to validate entries in the L2 query caches.
* </p>
*/
public class TableModState implements QueryCacheEntryValidate {
public class TableModState implements QueryCacheEntryValidate, ServerCacheNotify {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.TABLEMOD");
private Map<String,Long> tableModStamp = new ConcurrentHashMap<>();
/**
* Set the modified timestamp on the tables that have been touched.
*/
public void touch(Set<String> touchedTables, long modTimestamp) {
void touch(Set<String> touchedTables, long modTimestamp) {
for (String tableName : touchedTables) {
tableModStamp.put(tableName, modTimestamp);
}
if (log.isDebugEnabled()) {
log.debug("TableModState updated - " + tableModStamp);
}
}
/**
* Return true if all the tables are valid based on timestamp comparison.
*/
public boolean isValid(Set<String> tables, long sinceTimestamp) {
boolean isValid(Set<String> tables, long sinceTimestamp) {
for (String tableName : tables) {
Long modTime = tableModStamp.get(tableName);
if (modTime != null && modTime > sinceTimestamp ) {
@@ -48,4 +56,15 @@ public class TableModState implements QueryCacheEntryValidate {
}
return true;
}
/**
* Update the table modification timestamps based on remote table modification events.
*/
@Override
public void notify(ServerCacheNotification notification) {
// TODO: Change to use ClockService ...
long modifyTimestamp = notification.getModifyTimestamp();
touch(notification.getDependentTables(), modifyTimestamp);
}
}
@@ -5,6 +5,8 @@ import io.ebean.ProfileLocation;
import io.ebean.TxScope;
import io.ebean.annotation.PersistBatch;
import io.ebean.annotation.TxType;
import io.ebean.cache.ServerCacheNotification;
import io.ebean.cache.ServerCacheNotify;
import io.ebean.config.CurrentTenantProvider;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DatabasePlatform.OnQueryOnly;
@@ -137,6 +139,7 @@ public class TransactionManager implements SpiTransactionManager {
private final TransactionScopeManager scopeManager;
private final TableModState tableModState;
private final ServerCacheNotify cacheNotify;
/**
* Create the TransactionManager
@@ -160,6 +163,7 @@ public class TransactionManager implements SpiTransactionManager {
this.serverName = options.config.getName();
this.scopeManager = options.scopeManager;
this.tableModState = options.tableModState;
this.cacheNotify = options.cacheNotify;
this.backgroundExecutor = options.backgroundExecutor;
this.dataSourceSupplier = options.dataSourceSupplier;
this.docStoreActive = options.config.getDocStoreConfig().isActive();
@@ -510,6 +514,7 @@ public class TransactionManager implements SpiTransactionManager {
if (viewInvalidation) {
beanDescriptorManager.processViewInvalidation(touchedTables);
}
cacheNotify.notify(new ServerCacheNotification(modTimestamp, touchedTables));
}
/**
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.transaction;
import io.ebean.BackgroundExecutor;
import io.ebean.cache.ServerCacheNotify;
import io.ebean.config.ServerConfig;
import io.ebeaninternal.api.SpiLogManager;
import io.ebeaninternal.api.SpiProfileHandler;
@@ -25,12 +26,13 @@ public class TransactionManagerOptions {
final TransactionScopeManager scopeManager;
final SpiLogManager logManager;
final TableModState tableModState;
final ServerCacheNotify cacheNotify;
public TransactionManagerOptions(boolean notifyL2CacheInForeground, ServerConfig config, TransactionScopeManager scopeManager, ClusterManager clusterManager,
BackgroundExecutor backgroundExecutor, DocStoreUpdateProcessor docStoreUpdateProcessor,
BeanDescriptorManager descMgr, DataSourceSupplier dataSourceSupplier, SpiProfileHandler profileHandler,
SpiLogManager logManager, TableModState tableModState) {
SpiLogManager logManager, TableModState tableModState, ServerCacheNotify cacheNotify) {
this.notifyL2CacheInForeground = notifyL2CacheInForeground;
this.config = config;
@@ -43,6 +45,7 @@ public class TransactionManagerOptions {
this.profileHandler = profileHandler;
this.logManager = logManager;
this.tableModState = tableModState;
this.cacheNotify = cacheNotify;
}
}