From bd3c99e67f79ef588fa0b8e58f7790aa97143046 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Sat, 16 Jun 2018 00:22:44 +1200 Subject: [PATCH] #1427 - QueryCache should be cleared, if one of a dependent bean is updated Wrap Clock as ClockService to use in TransactionManager and DefaultServer (and allow for changing the Clock implementation for testing). --- .../server/core/ClockService.java | 29 +++++++++++++++++++ .../server/core/DefaultServer.java | 8 ++--- .../server/core/InternalConfiguration.java | 9 +++++- .../ImplicitReadOnlyTransaction.java | 2 +- .../server/transaction/JdbcTransaction.java | 2 +- .../transaction/TransactionManager.java | 9 ++++-- .../TransactionManagerOptions.java | 5 +++- 7 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 src/main/java/io/ebeaninternal/server/core/ClockService.java diff --git a/src/main/java/io/ebeaninternal/server/core/ClockService.java b/src/main/java/io/ebeaninternal/server/core/ClockService.java new file mode 100644 index 000000000..227a7b1cf --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/core/ClockService.java @@ -0,0 +1,29 @@ +package io.ebeaninternal.server.core; + +import java.time.Clock; + +/** + * Wraps the Clock such that we can change the Clock for testing purposes. + */ +public class ClockService { + + private Clock clock; + + public ClockService(Clock clock) { + this.clock = clock; + } + + /** + * Change the clock for testing purposes. + */ + public void setClock(Clock clock) { + this.clock = clock; + } + + /** + * Return the Clock current timestamp in millis. + */ + public long nowMillis() { + return clock.millis(); + } +} diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java index 89fe28b6b..a540ecb1b 100644 --- a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java @@ -154,7 +154,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { /** * Clock to use for WhenModified and WhenCreated. */ - private Clock clock; + private ClockService clockService; private final CallStackFactory callStackFactory; @@ -283,7 +283,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { this.beanLoader = new DefaultBeanLoader(this); this.jsonContext = config.createJsonContext(this); this.dataTimeZone = config.getDataTimeZone(); - this.clock = config.getServerConfig().getClock(); + this.clockService = config.getClockService(); DocStoreIntegration docStoreComponents = config.createDocStoreIntegration(this); this.transactionManager = config.createTransactionManager(docStoreComponents.updateProcessor()); @@ -515,12 +515,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { @Override public long clockNow() { - return clock.millis(); + return clockService.nowMillis(); } @Override public void setClock(Clock clock) { - this.clock = clock; + this.clockService.setClock(clock); } @Override diff --git a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java index 4beb65c58..f3b537217 100644 --- a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java +++ b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java @@ -122,6 +122,8 @@ public class InternalConfiguration { private final DtoBeanManager dtoBeanManager; + private final ClockService clockService; + private final DataTimeZone dataTimeZone; private final Binder binder; @@ -166,6 +168,7 @@ public class InternalConfiguration { this.online = online; this.serverConfig = serverConfig; + this.clockService = new ClockService(serverConfig.getClock()); this.logManager = initLogManager(); this.docStoreFactory = initDocStoreFactory(serverConfig.service(DocStoreFactory.class)); this.jsonFactory = serverConfig.getJsonFactory(); @@ -233,6 +236,10 @@ public class InternalConfiguration { return docStoreFactory; } + public ClockService getClockService() { + return clockService; + } + /** * Check if this is a SpiServerPlugin and if so 'collect' it to give the complete list * later on the DefaultServer for late call to configure(). @@ -423,7 +430,7 @@ public class InternalConfiguration { TransactionManagerOptions options = new TransactionManagerOptions(notifyL2CacheInForeground, serverConfig, scopeManager, clusterManager, backgroundExecutor, indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager, - tableModState, cacheNotify); + tableModState, cacheNotify, clockService); if (serverConfig.isExplicitTransactionBeginMode()) { return new ExplicitTransactionManager(options); diff --git a/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java b/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java index 1ccc44dbd..44e5b4bd1 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java +++ b/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java @@ -80,7 +80,7 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode this.connection = connection; this.persistenceContext = new DefaultPersistenceContext(); this.startNanos = System.nanoTime(); - this.startMillis = manager.clockNowEpoch(); + this.startMillis = manager.clockNowMillis(); } /** diff --git a/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java b/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java index da8e53781..2fbaab79a 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java +++ b/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java @@ -212,7 +212,7 @@ public class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes { this.batchOnCascadeMode = PersistBatch.NONE; this.onQueryOnly = OnQueryOnly.ROLLBACK; } else { - this.startMillis = manager.clockNowEpoch(); + this.startMillis = manager.clockNowMillis(); this.logSql = manager.isLogSql(); this.logSummary = manager.isLogSummary(); this.skipCacheAfterWrite = manager.isSkipCacheAfterWrite(); diff --git a/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java b/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java index b462b970b..4a007a9b3 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java +++ b/src/main/java/io/ebeaninternal/server/transaction/TransactionManager.java @@ -29,6 +29,7 @@ import io.ebeaninternal.metric.MetricFactory; import io.ebeaninternal.metric.TimedMetric; import io.ebeaninternal.metric.TimedMetricMap; import io.ebeaninternal.server.cluster.ClusterManager; +import io.ebeaninternal.server.core.ClockService; import io.ebeaninternal.server.deploy.BeanDescriptorManager; import io.ebeaninternal.server.profile.TimedProfileLocation; import io.ebeaninternal.server.profile.TimedProfileLocationRegistry; @@ -140,6 +141,7 @@ public class TransactionManager implements SpiTransactionManager { private final TableModState tableModState; private final ServerCacheNotify cacheNotify; + private final ClockService clockService; /** * Create the TransactionManager @@ -164,6 +166,7 @@ public class TransactionManager implements SpiTransactionManager { this.scopeManager = options.scopeManager; this.tableModState = options.tableModState; this.cacheNotify = options.cacheNotify; + this.clockService = options.clockService; this.backgroundExecutor = options.backgroundExecutor; this.dataSourceSupplier = options.dataSourceSupplier; this.docStoreActive = options.config.getDocStoreConfig().isActive(); @@ -188,8 +191,8 @@ public class TransactionManager implements SpiTransactionManager { /** * Return the NOW timestamp in epoch millis. */ - public long clockNowEpoch() { - return System.currentTimeMillis(); // TODO: Review when we supply a Clock via ServerConfig. + public long clockNowMillis() { + return clockService.nowMillis(); } /** @@ -448,7 +451,7 @@ public class TransactionManager implements SpiTransactionManager { private void externalModificationEvent(TransactionEventTable tableEvents) { - TransactionEvent event = new TransactionEvent(clockNowEpoch()); + TransactionEvent event = new TransactionEvent(clockNowMillis()); event.add(tableEvents); PostCommitProcessing postCommit = new PostCommitProcessing(clusterManager, this, event); diff --git a/src/main/java/io/ebeaninternal/server/transaction/TransactionManagerOptions.java b/src/main/java/io/ebeaninternal/server/transaction/TransactionManagerOptions.java index 1b8ce39a8..f55389a19 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/TransactionManagerOptions.java +++ b/src/main/java/io/ebeaninternal/server/transaction/TransactionManagerOptions.java @@ -6,6 +6,7 @@ import io.ebean.config.ServerConfig; import io.ebeaninternal.api.SpiLogManager; import io.ebeaninternal.api.SpiProfileHandler; import io.ebeaninternal.server.cluster.ClusterManager; +import io.ebeaninternal.server.core.ClockService; import io.ebeaninternal.server.deploy.BeanDescriptorManager; import io.ebeanservice.docstore.api.DocStoreUpdateProcessor; @@ -27,12 +28,13 @@ public class TransactionManagerOptions { final SpiLogManager logManager; final TableModState tableModState; final ServerCacheNotify cacheNotify; + final ClockService clockService; public TransactionManagerOptions(boolean notifyL2CacheInForeground, ServerConfig config, TransactionScopeManager scopeManager, ClusterManager clusterManager, BackgroundExecutor backgroundExecutor, DocStoreUpdateProcessor docStoreUpdateProcessor, BeanDescriptorManager descMgr, DataSourceSupplier dataSourceSupplier, SpiProfileHandler profileHandler, - SpiLogManager logManager, TableModState tableModState, ServerCacheNotify cacheNotify) { + SpiLogManager logManager, TableModState tableModState, ServerCacheNotify cacheNotify, ClockService clockService) { this.notifyL2CacheInForeground = notifyL2CacheInForeground; this.config = config; @@ -46,6 +48,7 @@ public class TransactionManagerOptions { this.logManager = logManager; this.tableModState = tableModState; this.cacheNotify = cacheNotify; + this.clockService = clockService; } }