From ae228d6b0e6a0d82c2ce80f9d7c1d63b5b08c0c4 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Wed, 24 Apr 2019 14:00:22 +1200 Subject: [PATCH] #1679 - ENH: Support enabling/disabling L2 cache by "region" at runtime --- pom.xml | 2 +- .../io/ebean/cache/ServerCacheManager.java | 31 +++++++- .../io/ebean/cache/ServerCacheRegion.java | 23 ++++++ .../io/ebeaninternal/api/SpiCacheControl.java | 25 +++++++ .../io/ebeaninternal/api/SpiCacheRegion.java | 10 +++ .../server/cache/DefaultCacheAdapter.java | 23 ++++++ .../cache/DefaultServerCacheManager.java | 56 ++++++++++++++ .../server/cache/SpiCacheManager.java | 26 +++++++ .../server/core/CacheOptions.java | 37 +++++---- .../deploy/BeanDescriptorCacheHelp.java | 56 +++++++++++--- .../server/deploy/DCacheControl.java | 42 +++++++++++ .../server/deploy/DCacheControlNone.java | 31 ++++++++ .../server/deploy/DCacheRegion.java | 29 +++++++ .../server/deploy/DCacheRegionNone.java | 23 ++++++ .../cache/personinfo/PersonCacheEmail.java | 2 +- .../cache/personinfo/PersonCacheInfo.java | 2 +- .../cache/personinfo/PersonCacheTests.java | 75 +++++++++++++++---- 17 files changed, 451 insertions(+), 42 deletions(-) create mode 100644 src/main/java/io/ebean/cache/ServerCacheRegion.java create mode 100644 src/main/java/io/ebeaninternal/api/SpiCacheControl.java create mode 100644 src/main/java/io/ebeaninternal/api/SpiCacheRegion.java create mode 100644 src/main/java/io/ebeaninternal/server/deploy/DCacheControl.java create mode 100644 src/main/java/io/ebeaninternal/server/deploy/DCacheControlNone.java create mode 100644 src/main/java/io/ebeaninternal/server/deploy/DCacheRegion.java create mode 100644 src/main/java/io/ebeaninternal/server/deploy/DCacheRegionNone.java diff --git a/pom.xml b/pom.xml index b39a81bf7..a3ed6d149 100644 --- a/pom.xml +++ b/pom.xml @@ -117,7 +117,7 @@ io.ebean ebean-annotation - 4.7 + 4.8 diff --git a/src/main/java/io/ebean/cache/ServerCacheManager.java b/src/main/java/io/ebean/cache/ServerCacheManager.java index 38de72fc6..a81fe9a52 100644 --- a/src/main/java/io/ebean/cache/ServerCacheManager.java +++ b/src/main/java/io/ebean/cache/ServerCacheManager.java @@ -1,5 +1,7 @@ package io.ebean.cache; +import java.util.List; + /** * The cache service for server side caching of beans and query results. */ @@ -14,6 +16,31 @@ public interface ServerCacheManager { */ boolean isLocalL2Caching(); + /** + * Return all the cache regions. + */ + List allRegions(); + + /** + * Set the regions that are enabled. + *

+ * Typically this is set on startup and at runtime (via dynamic configuration). + *

+ * + * @param regions A region name or comma delimited list of region names. + */ + void setEnabledRegions(String regions); + + /** + * Enable or disable all the cache regions. + */ + void setAllRegionsEnabled(boolean enabled); + + /** + * Return the cache region by name. Typically to enable or disable the region. + */ + ServerCacheRegion getRegion(String name); + /** * Return the cache for mapping natural keys to id values. */ @@ -46,7 +73,7 @@ public interface ServerCacheManager { /** * Clear all the local caches. - * + *

* This is used when the L2 Cache is based on clustered near-caches (Like Ebean-K8s-L2Cache). * It is not used when the L2 cache is a distributed cache such as HazelCast or Ignite etc. */ @@ -54,7 +81,7 @@ public interface ServerCacheManager { /** * Clear the local caches for this bean type. - * + *

* This is used when the L2 Cache is based on clustered near-caches (Like Ebean-K8s-L2Cache). * It is not used when the L2 cache is a distributed cache such as HazelCast or Ignite etc. */ diff --git a/src/main/java/io/ebean/cache/ServerCacheRegion.java b/src/main/java/io/ebean/cache/ServerCacheRegion.java new file mode 100644 index 000000000..b63668d91 --- /dev/null +++ b/src/main/java/io/ebean/cache/ServerCacheRegion.java @@ -0,0 +1,23 @@ +package io.ebean.cache; + +/** + * Cache region can be enabled independently. + */ +public interface ServerCacheRegion { + + /** + * Return the region name. + */ + String getName(); + + /** + * Return true if the cache region is enabled. + */ + boolean isEnabled(); + + /** + * Set to true to enable the cache region. + */ + void setEnabled(boolean enabled); + +} diff --git a/src/main/java/io/ebeaninternal/api/SpiCacheControl.java b/src/main/java/io/ebeaninternal/api/SpiCacheControl.java new file mode 100644 index 000000000..17e2fbe17 --- /dev/null +++ b/src/main/java/io/ebeaninternal/api/SpiCacheControl.java @@ -0,0 +1,25 @@ +package io.ebeaninternal.api; + +public interface SpiCacheControl { + + /** + * Return true if bean caching or query caching. + */ + boolean isCaching(); + + /** + * Return true if bean caching. + */ + boolean isBeanCaching(); + + /** + * Return true if natural key caching. + */ + boolean isNaturalKeyCaching(); + + /** + * Return true if query caching. + */ + boolean isQueryCaching(); + +} diff --git a/src/main/java/io/ebeaninternal/api/SpiCacheRegion.java b/src/main/java/io/ebeaninternal/api/SpiCacheRegion.java new file mode 100644 index 000000000..78595b110 --- /dev/null +++ b/src/main/java/io/ebeaninternal/api/SpiCacheRegion.java @@ -0,0 +1,10 @@ +package io.ebeaninternal.api; + +import io.ebean.cache.ServerCacheRegion; + +/** + * Cache region can be enabled independently. + */ +public interface SpiCacheRegion extends ServerCacheRegion { + +} diff --git a/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java b/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java index 0c3cfa9e5..37e89b864 100644 --- a/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java +++ b/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java @@ -2,6 +2,9 @@ package io.ebeaninternal.server.cache; import io.ebean.cache.ServerCache; import io.ebean.cache.ServerCacheManager; +import io.ebean.cache.ServerCacheRegion; + +import java.util.List; /** * Adapts SpiCacheManager to ServerCacheManager. @@ -22,6 +25,26 @@ public class DefaultCacheAdapter implements ServerCacheManager { return cacheManager.isLocalL2Caching(); } + @Override + public List allRegions() { + return cacheManager.allRegions(); + } + + @Override + public void setEnabledRegions(String regions) { + cacheManager.setEnabledRegions(regions); + } + + @Override + public ServerCacheRegion getRegion(String region) { + return cacheManager.getRegion(region); + } + + @Override + public void setAllRegionsEnabled(boolean enabled) { + cacheManager.setAllRegionsEnabled(enabled); + } + @Override public ServerCache getNaturalKeyCache(Class beanType) { return cacheManager.getNaturalKeyCache(beanType); diff --git a/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheManager.java b/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheManager.java index bdb10d453..bf4fadac6 100644 --- a/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheManager.java +++ b/src/main/java/io/ebeaninternal/server/cache/DefaultServerCacheManager.java @@ -1,14 +1,29 @@ package io.ebeaninternal.server.cache; import io.ebean.cache.ServerCache; +import io.ebean.cache.ServerCacheRegion; import io.ebean.cache.ServerCacheType; +import io.ebeaninternal.api.SpiCacheRegion; import io.ebeaninternal.server.cluster.ClusterManager; +import io.ebeaninternal.server.deploy.DCacheRegion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Manages the bean and query caches. */ public class DefaultServerCacheManager implements SpiCacheManager { + private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.REGION"); + + private final Map regionMap = new HashMap<>(); + private final ClusterManager clusterManager; private final DefaultCacheHolder cacheHolder; @@ -39,6 +54,47 @@ public class DefaultServerCacheManager implements SpiCacheManager { return localL2Caching; } + @Override + public List allRegions() { + return new ArrayList<>(regionMap.values()); + } + + @Override + public void setEnabledRegions(String regions) { + + List enabledRegions = Arrays.asList(regions.split(",")); + List disabledRegions = new ArrayList<>(); + + for (SpiCacheRegion region : regionMap.values()) { + if (enabledRegions.contains(region.getName())) { + if (!region.isEnabled()) { + region.setEnabled(true); + log.debug("Cache region[{}] enabled", region.getName()); + } + } else { + disabledRegions.add(region.getName()); + if (region.isEnabled()) { + region.setEnabled(false); + log.debug("Cache region[{}] disabled", region.getName()); + } + } + } + log.info("Cache regions enabled:{} disabled:{}", enabledRegions, disabledRegions); + } + + @Override + public void setAllRegionsEnabled(boolean enabled) { + log.debug("All cache regions enabled[{}]", enabled); + for (SpiCacheRegion region : regionMap.values()) { + region.setEnabled(enabled); + } + } + + @Override + public SpiCacheRegion getRegion(String region) { + return regionMap.computeIfAbsent(region, DCacheRegion::new); + } + /** * Clear all caches. */ diff --git a/src/main/java/io/ebeaninternal/server/cache/SpiCacheManager.java b/src/main/java/io/ebeaninternal/server/cache/SpiCacheManager.java index 3e83203bd..5ef06b991 100644 --- a/src/main/java/io/ebeaninternal/server/cache/SpiCacheManager.java +++ b/src/main/java/io/ebeaninternal/server/cache/SpiCacheManager.java @@ -1,6 +1,10 @@ package io.ebeaninternal.server.cache; import io.ebean.cache.ServerCache; +import io.ebean.cache.ServerCacheRegion; +import io.ebeaninternal.api.SpiCacheRegion; + +import java.util.List; /** * The cache service for server side caching of beans and query results. @@ -16,6 +20,28 @@ public interface SpiCacheManager { */ boolean isLocalL2Caching(); + /** + * Return all the regions. + */ + List allRegions(); + + /** + * Set the regions that are enabled. + * + * @param regions A single region name or a comma delimited list of region names. + */ + void setEnabledRegions(String regions); + + /** + * Enable or disable all cache regions. + */ + void setAllRegionsEnabled(boolean enabled); + + /** + * Return the cache region. We can enable L2 caching by region. + */ + SpiCacheRegion getRegion(String region); + /** * Return the cache for mapping natural keys to id values. */ diff --git a/src/main/java/io/ebeaninternal/server/core/CacheOptions.java b/src/main/java/io/ebeaninternal/server/core/CacheOptions.java index 24d441828..5fd2fcf54 100644 --- a/src/main/java/io/ebeaninternal/server/core/CacheOptions.java +++ b/src/main/java/io/ebeaninternal/server/core/CacheOptions.java @@ -19,16 +19,18 @@ public class CacheOptions { private final boolean enableQueryCache; private final boolean readOnly; private final String[] naturalKey; + private final String region; /** * Construct for no caching. */ private CacheOptions() { - invalidateQueryCache = false; - enableBeanCache = false; - enableQueryCache = false; - readOnly = false; - naturalKey = null; + this.invalidateQueryCache = false; + this.enableBeanCache = false; + this.enableQueryCache = false; + this.readOnly = false; + this.naturalKey = null; + this.region = null; } /** @@ -36,21 +38,30 @@ public class CacheOptions { */ private CacheOptions(boolean invalidateQueryCache) { this.invalidateQueryCache = invalidateQueryCache; - enableBeanCache = false; - enableQueryCache = false; - readOnly = false; - naturalKey = null; + this.enableBeanCache = false; + this.enableQueryCache = false; + this.readOnly = false; + this.naturalKey = null; + this.region = null; } /** * Construct with cache annotation. */ public CacheOptions(Cache cache, String[] naturalKey) { - invalidateQueryCache = false; - enableBeanCache = cache.enableBeanCache(); - enableQueryCache = cache.enableQueryCache(); - readOnly = cache.readOnly(); + this.invalidateQueryCache = false; + this.enableBeanCache = cache.enableBeanCache(); + this.enableQueryCache = cache.enableQueryCache(); + this.readOnly = cache.readOnly(); this.naturalKey = naturalKey; + this.region = cache.region(); + } + + /** + * Return the cache region name. + */ + public String getRegion() { + return region; } /** diff --git a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java index 88c816040..b2cb88ffb 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java +++ b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java @@ -7,6 +7,8 @@ import io.ebean.bean.PersistenceContext; import io.ebean.cache.QueryCacheEntry; import io.ebean.cache.ServerCache; import io.ebeaninternal.api.BeanCacheResult; +import io.ebeaninternal.api.SpiCacheControl; +import io.ebeaninternal.api.SpiCacheRegion; import io.ebeaninternal.api.SpiTransaction; import io.ebeaninternal.api.TransactionEventTable.TableIUD; import io.ebeaninternal.server.cache.CacheChangeSet; @@ -72,6 +74,9 @@ final class BeanDescriptorCacheHelp { private final boolean noCaching; + private final SpiCacheControl cacheControl; + private final SpiCacheRegion cacheRegion; + /** * Set to true if all persist changes need to notify the cache. */ @@ -113,6 +118,13 @@ final class BeanDescriptorCacheHelp { this.naturalKeyCache = null; } this.noCaching = (beanCache == null && queryCache == null); + if (noCaching) { + this.cacheControl = DCacheControlNone.INSTANCE; + this.cacheRegion = (invalidateQueryCache) ? cacheManager.getRegion(cacheOptions.getRegion()) : DCacheRegionNone.INSTANCE; + } else { + this.cacheRegion = cacheManager.getRegion(cacheOptions.getRegion()); + this.cacheControl = new DCacheControl(cacheRegion, (beanCache != null), (naturalKeyCache != null), (queryCache != null)); + } } /** @@ -123,8 +135,8 @@ final class BeanDescriptorCacheHelp { cacheNotifyOnDelete = !cacheNotifyOnAll && isNotifyOnDeletes(); if (logger.isDebugEnabled()) { - if (isBeanCaching() || isQueryCaching() || cacheNotifyOnAll || cacheNotifyOnDelete) { - String notifyMode = cacheNotifyOnAll ? "All" : (cacheNotifyOnDelete ? "Delete" : "None"); + if (cacheNotifyOnAll || cacheNotifyOnDelete) { + String notifyMode = cacheNotifyOnAll ? "All" : "Delete"; logger.debug("l2 caching on {} - beanCaching:{} queryCaching:{} notifyMode:{} ", desc.getFullName(), isBeanCaching(), isQueryCaching(), notifyMode); } @@ -148,36 +160,36 @@ final class BeanDescriptorCacheHelp { * Return true if the persist request needs to notify the cache. */ boolean isCacheNotify(PersistRequest.Type type) { - return cacheNotifyOnAll - || cacheNotifyOnDelete && (type == PersistRequest.Type.DELETE || type == PersistRequest.Type.DELETE_PERMANENT); + return cacheRegion.isEnabled() + && (cacheNotifyOnAll || cacheNotifyOnDelete && (type == PersistRequest.Type.DELETE || type == PersistRequest.Type.DELETE_PERMANENT)); } /** * Return true if there is currently query caching for this type of bean. */ boolean isQueryCaching() { - return queryCache != null; + return cacheControl.isQueryCaching(); } /** * Return true if there is currently bean caching for this type of bean. */ boolean isBeanCaching() { - return beanCache != null; + return cacheControl.isBeanCaching(); } /** * Return true if there is natural key caching for this type of bean. */ boolean isNaturalKeyCaching() { - return naturalKeyCache != null; + return cacheControl.isNaturalKeyCaching(); } /** * Return true if there is bean or query caching on this type. */ boolean isCaching() { - return beanCache != null || queryCache != null; + return cacheControl.isCaching(); } /** @@ -206,7 +218,7 @@ final class BeanDescriptorCacheHelp { /** * Add query cache clear to the changeSet. */ - void queryCacheClear(CacheChangeSet changeSet) { + private void queryCacheClear(CacheChangeSet changeSet) { if (queryCache != null) { changeSet.addClearQuery(desc); } @@ -292,8 +304,8 @@ final class BeanDescriptorCacheHelp { return false; } - Object ownerBean = bc.getOwnerBean(); - EntityBeanIntercept ebi = ((EntityBean) ownerBean)._ebean_getIntercept(); + EntityBean ownerBean = bc.getOwnerBean(); + EntityBeanIntercept ebi = ownerBean._ebean_getIntercept(); PersistenceContext persistenceContext = ebi.getPersistenceContext(); BeanDescriptor targetDescriptor = many.getTargetDescriptor(); @@ -362,6 +374,28 @@ final class BeanDescriptorCacheHelp { return new CachedManyIds(idList); } +// BeanCacheResult cacheIdLookup(PersistenceContext context, Collection keys) { +// +// Set ids = new HashSet<>(keys); +// Map beanDataMap = beanCache.getAll(ids); +// if (beanLog.isTraceEnabled()) { +// beanLog.trace(" GET MANY {}({}) - hits:{}", cacheName, ids, beanDataMap.keySet()); +// } +// +// BeanCacheResult result = new BeanCacheResult<>(); +// // process the hits into beans etc +// for (Map.Entry entry : beanDataMap.entrySet()) { +// +// Object id = entry.getKey(); +// CachedBeanData cachedBeanData = (CachedBeanData) entry.getValue(); +// +// T bean = convertToBean(id, false, context, cachedBeanData); +// result.add(bean, id); +// } +// +// return result; +// } + /** * Use natural keys to hit the bean cache and return resulting hits. */ diff --git a/src/main/java/io/ebeaninternal/server/deploy/DCacheControl.java b/src/main/java/io/ebeaninternal/server/deploy/DCacheControl.java new file mode 100644 index 000000000..a99dabf89 --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/deploy/DCacheControl.java @@ -0,0 +1,42 @@ +package io.ebeaninternal.server.deploy; + +import io.ebeaninternal.api.SpiCacheControl; +import io.ebeaninternal.api.SpiCacheRegion; + +/** + * Default implementation of SpiCacheControl. + */ +class DCacheControl implements SpiCacheControl { + + private final SpiCacheRegion region; + private final boolean bean; + private final boolean naturalKey; + private final boolean query; + + DCacheControl(SpiCacheRegion region, boolean bean, boolean naturalKey, boolean query) { + this.region = region; + this.bean = bean; + this.naturalKey = naturalKey; + this.query = query; + } + + @Override + public boolean isCaching() { + return (bean || query) && region.isEnabled(); + } + + @Override + public boolean isBeanCaching() { + return bean && region.isEnabled(); + } + + @Override + public boolean isNaturalKeyCaching() { + return naturalKey && region.isEnabled(); + } + + @Override + public boolean isQueryCaching() { + return query && region.isEnabled(); + } +} diff --git a/src/main/java/io/ebeaninternal/server/deploy/DCacheControlNone.java b/src/main/java/io/ebeaninternal/server/deploy/DCacheControlNone.java new file mode 100644 index 000000000..8f4797f47 --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/deploy/DCacheControlNone.java @@ -0,0 +1,31 @@ +package io.ebeaninternal.server.deploy; + +import io.ebeaninternal.api.SpiCacheControl; + +/** + * Cache control used when no caching is on the bean type. + */ +class DCacheControlNone implements SpiCacheControl { + + static final SpiCacheControl INSTANCE = new DCacheControlNone(); + + @Override + public boolean isCaching() { + return false; + } + + @Override + public boolean isBeanCaching() { + return false; + } + + @Override + public boolean isNaturalKeyCaching() { + return false; + } + + @Override + public boolean isQueryCaching() { + return false; + } +} diff --git a/src/main/java/io/ebeaninternal/server/deploy/DCacheRegion.java b/src/main/java/io/ebeaninternal/server/deploy/DCacheRegion.java new file mode 100644 index 000000000..2056833b7 --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/deploy/DCacheRegion.java @@ -0,0 +1,29 @@ +package io.ebeaninternal.server.deploy; + +import io.ebeaninternal.api.SpiCacheRegion; + +public class DCacheRegion implements SpiCacheRegion { + + private boolean enabled = true; + + private final String name; + + public DCacheRegion(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} diff --git a/src/main/java/io/ebeaninternal/server/deploy/DCacheRegionNone.java b/src/main/java/io/ebeaninternal/server/deploy/DCacheRegionNone.java new file mode 100644 index 000000000..50c9ba33a --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/deploy/DCacheRegionNone.java @@ -0,0 +1,23 @@ +package io.ebeaninternal.server.deploy; + +import io.ebeaninternal.api.SpiCacheRegion; + +class DCacheRegionNone implements SpiCacheRegion { + + static SpiCacheRegion INSTANCE = new DCacheRegionNone(); + + @Override + public String getName() { + return ""; + } + + @Override + public boolean isEnabled() { + return false; + } + + @Override + public void setEnabled(boolean enabled) { + throw new IllegalStateException("Not expected"); + } +} diff --git a/src/test/java/org/tests/cache/personinfo/PersonCacheEmail.java b/src/test/java/org/tests/cache/personinfo/PersonCacheEmail.java index e78463fe9..58ddea0a2 100644 --- a/src/test/java/org/tests/cache/personinfo/PersonCacheEmail.java +++ b/src/test/java/org/tests/cache/personinfo/PersonCacheEmail.java @@ -8,7 +8,7 @@ import javax.persistence.ManyToOne; import javax.validation.constraints.Size; @Entity -@Cache +@Cache(region = "email") public class PersonCacheEmail { @Id diff --git a/src/test/java/org/tests/cache/personinfo/PersonCacheInfo.java b/src/test/java/org/tests/cache/personinfo/PersonCacheInfo.java index bc24ce960..25d8e4d51 100644 --- a/src/test/java/org/tests/cache/personinfo/PersonCacheInfo.java +++ b/src/test/java/org/tests/cache/personinfo/PersonCacheInfo.java @@ -7,7 +7,7 @@ import javax.persistence.Id; import javax.validation.constraints.Size; @Entity -@Cache +@Cache(region = "email") public class PersonCacheInfo { @Id diff --git a/src/test/java/org/tests/cache/personinfo/PersonCacheTests.java b/src/test/java/org/tests/cache/personinfo/PersonCacheTests.java index 5cc192eca..b92949f6d 100644 --- a/src/test/java/org/tests/cache/personinfo/PersonCacheTests.java +++ b/src/test/java/org/tests/cache/personinfo/PersonCacheTests.java @@ -1,17 +1,31 @@ package org.tests.cache.personinfo; -import io.ebean.Ebean; +import io.ebean.DB; import io.ebean.cache.ServerCache; +import io.ebean.cache.ServerCacheRegion; +import io.ebean.cache.ServerCacheStatistics; import org.ebeantest.LoggedSqlCollector; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; public class PersonCacheTests { + private static final Logger log = LoggerFactory.getLogger(PersonCacheTests.class); + + private final List ids = Arrays.asList("E001", "E002", "E003"); + + private ServerCache beanCacheInfo = DB.getDefault().getServerCacheManager().getBeanCache(PersonCacheInfo.class); + private ServerCache beanCacheEmail = DB.getDefault().getServerCacheManager().getBeanCache(PersonCacheEmail.class); + + private ServerCacheRegion region = DB.getDefault().getServerCacheManager().getRegion("email"); + private void insert(int id, String email) { PersonCacheInfo person = new PersonCacheInfo("P00" + id, "P00" + id); @@ -19,8 +33,8 @@ public class PersonCacheTests { PersonCacheEmail personEmail = new PersonCacheEmail("E00" + id, email); personEmail.setPersonInfo(person); - Ebean.save(person); - Ebean.save(personEmail); + DB.save(person); + DB.save(personEmail); } private void addTestData() { @@ -37,18 +51,15 @@ public class PersonCacheTests { LoggedSqlCollector.start(); - Ebean.find(PersonCacheInfo.class) + DB.find(PersonCacheInfo.class) .select("personId") // do not fetch name .setUseCache(true) .findList(); - ServerCache beanCache = Ebean.getDefaultServer().getServerCacheManager().getBeanCache(PersonCacheInfo.class); - beanCache.getStatistics(true); - - List ids = Arrays.asList(new String[]{"E001", "E002", "E003"}); + beanCacheInfo.getStatistics(true); List emailList = - Ebean.find(PersonCacheEmail.class) + DB.find(PersonCacheEmail.class) .where().idIn(ids) .setUseCache(true) .findList(); @@ -63,12 +74,12 @@ public class PersonCacheTests { List sql = LoggedSqlCollector.current(); assertThat(sql).hasSize(3); - assertThat(beanCache.getStatistics(true).getHitCount()).isEqualTo(3); + assertThat(beanCacheInfo.getStatistics(true).getHitCount()).isEqualTo(3); - System.out.println("Fetch again ..."); + log.info("Fetch again ..."); emailList = - Ebean.find(PersonCacheEmail.class) + DB.find(PersonCacheEmail.class) .where().idIn(ids) .setUseCache(true) .findList(); @@ -83,7 +94,45 @@ public class PersonCacheTests { sql = LoggedSqlCollector.stop(); assertThat(sql).hasSize(1); - assertThat(beanCache.getStatistics(true).getHitCount()).isEqualTo(3); + assertThat(beanCacheInfo.getStatistics(true).getHitCount()).isEqualTo(3); + + turnOffRegion_expect_noCacheUse(); } + + private void turnOffRegion_expect_noCacheUse() { + + assertTrue(region.isEnabled()); + beanCacheEmail.getStatistics(true); + + log.info("Disabled region ..."); + region.setEnabled(false); + + for (Object id : ids) { + DB.find(PersonCacheEmail.class) + .where().idEq(id) + .setUseCache(true) + .findOne(); + } + + // assert that we didn't hit the cache + ServerCacheStatistics statistics = beanCacheEmail.getStatistics(true); + assertThat(statistics.getHitCount()).isEqualTo(0); + assertThat(statistics.getMissCount()).isEqualTo(0); + + log.info("Enabled region ..."); + region.setEnabled(true); + + for (Object id : ids) { + DB.find(PersonCacheEmail.class) + .where().idEq(id) + .setUseCache(true) + .findOne(); + } + + // assert that we DID hit the cache + statistics = beanCacheEmail.getStatistics(true); + assertThat(statistics.getHitCount()).isEqualTo(3); + assertThat(statistics.getMissCount()).isEqualTo(0); + } }