From 5aaed4e12b8b7bb0a77c7646841366c4a67eb7f9 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Tue, 26 May 2020 23:42:44 +1200 Subject: [PATCH] #2016 - L2 Cache - missing puts with explicit bean cache + findByIds/keys + after transaction writes --- .../io/ebeaninternal/api/SpiTransaction.java | 5 ++ .../api/SpiTransactionProxy.java | 5 ++ .../server/core/OrmQueryRequest.java | 4 ++ .../server/query/DefaultOrmQueryEngine.java | 2 +- .../ImplicitReadOnlyTransaction.java | 5 ++ .../server/transaction/JdbcTransaction.java | 5 ++ .../server/transaction/NoTransaction.java | 5 ++ .../java/org/tests/cache/TestBeanCache.java | 51 +++++++++++++++---- 8 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/main/java/io/ebeaninternal/api/SpiTransaction.java b/src/main/java/io/ebeaninternal/api/SpiTransaction.java index eb6422ba6..a9b14c18a 100644 --- a/src/main/java/io/ebeaninternal/api/SpiTransaction.java +++ b/src/main/java/io/ebeaninternal/api/SpiTransaction.java @@ -313,4 +313,9 @@ public interface SpiTransaction extends Transaction { * Return true when nested transactions should create Savepoints. */ boolean isNestedUseSavepoint(); + + /** + * Return true if explicitly set to skip cache (ignores skipOnWrite). + */ + boolean isSkipCacheExplicit(); } diff --git a/src/main/java/io/ebeaninternal/api/SpiTransactionProxy.java b/src/main/java/io/ebeaninternal/api/SpiTransactionProxy.java index 31f83c06a..897a32f44 100644 --- a/src/main/java/io/ebeaninternal/api/SpiTransactionProxy.java +++ b/src/main/java/io/ebeaninternal/api/SpiTransactionProxy.java @@ -158,6 +158,11 @@ public abstract class SpiTransactionProxy implements SpiTransaction { transaction.setSkipCache(skipCache); } + @Override + public boolean isSkipCacheExplicit() { + return transaction.isSkipCacheExplicit(); + } + @Override public boolean isSkipCache() { return transaction.isSkipCache(); diff --git a/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java index bf299983a..7a4cb412a 100644 --- a/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java +++ b/src/main/java/io/ebeaninternal/server/core/OrmQueryRequest.java @@ -578,6 +578,10 @@ public final class OrmQueryRequest extends BeanRequest implements SpiOrmQuery return cacheKey != null && query.getUseQueryCache().isPut(); } + public boolean isBeanCachePutMany() { + return !transaction.isSkipCacheExplicit() && query.isBeanCachePut(); + } + public boolean isBeanCachePut() { return !transaction.isSkipCache() && query.isBeanCachePut(); } diff --git a/src/main/java/io/ebeaninternal/server/query/DefaultOrmQueryEngine.java b/src/main/java/io/ebeaninternal/server/query/DefaultOrmQueryEngine.java index 7423a0d0d..1c59a614e 100644 --- a/src/main/java/io/ebeaninternal/server/query/DefaultOrmQueryEngine.java +++ b/src/main/java/io/ebeaninternal/server/query/DefaultOrmQueryEngine.java @@ -133,7 +133,7 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine { SpiQuery query = request.getQuery(); - if (request.isBeanCachePut()) { + if (request.isBeanCachePutMany()) { // load the individual beans into the bean cache BeanDescriptor descriptor = request.getBeanDescriptor(); Collection c = result.getActualDetails(); diff --git a/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java b/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java index 487c910e8..53d266964 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java +++ b/src/main/java/io/ebeaninternal/server/transaction/ImplicitReadOnlyTransaction.java @@ -140,6 +140,11 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode return false; } + @Override + public boolean isSkipCacheExplicit() { + return false; + } + @Override public void setSkipCache(boolean skipCache) { } diff --git a/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java b/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java index 6274f0fcb..a45e7366e 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java +++ b/src/main/java/io/ebeaninternal/server/transaction/JdbcTransaction.java @@ -293,6 +293,11 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes { return sb.toString(); } + @Override + public boolean isSkipCacheExplicit() { + return (skipCache != null && !skipCache); + } + @Override public boolean isSkipCache() { if (skipCache != null) return skipCache; diff --git a/src/main/java/io/ebeaninternal/server/transaction/NoTransaction.java b/src/main/java/io/ebeaninternal/server/transaction/NoTransaction.java index bfc88f69f..48476c14a 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/NoTransaction.java +++ b/src/main/java/io/ebeaninternal/server/transaction/NoTransaction.java @@ -200,6 +200,11 @@ class NoTransaction implements SpiTransaction { public void setSkipCache(boolean skipCache) { } + @Override + public boolean isSkipCacheExplicit() { + return false; + } + @Override public boolean isSkipCache() { return false; diff --git a/src/test/java/org/tests/cache/TestBeanCache.java b/src/test/java/org/tests/cache/TestBeanCache.java index c7a9cf74e..99e40879d 100644 --- a/src/test/java/org/tests/cache/TestBeanCache.java +++ b/src/test/java/org/tests/cache/TestBeanCache.java @@ -2,6 +2,7 @@ package org.tests.cache; import io.ebean.BaseTestCase; import io.ebean.DB; +import io.ebean.Transaction; import io.ebean.cache.ServerCache; import io.ebean.cache.ServerCacheStatistics; import org.ebeantest.LoggedSqlCollector; @@ -26,7 +27,7 @@ public class TestBeanCache extends BaseTestCase { private static final Logger log = LoggerFactory.getLogger(TestBeanCache.class); - private ServerCache beanCache = DB.getDefault().getServerCacheManager().getBeanCache(OCachedBean.class); + private final ServerCache beanCache = DB.getDefault().getServerCacheManager().getBeanCache(OCachedBean.class); @Test public void findById_when_idTypeConverted() { @@ -53,10 +54,39 @@ public class TestBeanCache extends BaseTestCase { assertThat(sql).isEmpty(); } + @Test + public void idsIn_explicitCache_expect_cachePut() { + + List beans = createBeans(Arrays.asList("k0","k1")); + List ids = beans.stream().map(OCachedBean::getId).collect(Collectors.toList()); + + beanCache.clear(); + beanCache.getStatistics(true); + try (Transaction transaction = DB.beginTransaction()) { + + // skipCacheAfterWrite set after this write ... + final OCachedBean junk = createBean("junk"); + DB.save(junk); + + List list = DB.find(OCachedBean.class) + .where().idIn(ids) + .setUseCache(true) + .findList(); + + assertThat(list).hasSize(2); + transaction.commit(); + } + + ServerCacheStatistics statistics = beanCache.getStatistics(true); + assertThat(statistics.getHitCount()).isEqualTo(0); + assertThat(statistics.getMissCount()).isEqualTo(2); + assertThat(statistics.getPutCount()).isEqualTo(2); + } + @Test public void idsInExpression() { - List beans = createBeans(); + List beans = createBeans(Arrays.asList("z0", "z1", "z2")); List ids = beans.stream().map(OCachedBean::getId).collect(Collectors.toList()); beanCache.clear(); @@ -133,22 +163,21 @@ public class TestBeanCache extends BaseTestCase { assertThat(statistics.getMissCount()).isEqualTo(missCount); } - private List createBeans() { - - List names = Arrays.asList("z0", "z1", "z2"); - + private List createBeans(List names) { List beans = new ArrayList<>(); for (String name : names) { - OCachedBean bean = new OCachedBean(); - bean.setName(name); - beans.add(bean); + beans.add(createBean(name)); } - DB.saveAll(beans); - return beans; } + private OCachedBean createBean(String name) { + OCachedBean bean = new OCachedBean(); + bean.setName(name); + return bean; + } + @Test public void find_whenNotExits() {