From 6858cf6f489e9f99046ed4d5154fccf0ce729e66 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Wed, 7 Feb 2018 18:41:39 -0500 Subject: [PATCH] Integrate JCache for cached objects outside of a UnitOfWork. --- pom.xml | 19 ++- .../java/net/helenus/core/HelenusSession.java | 138 ++++++++++-------- .../net/helenus/core/SessionInitializer.java | 36 ++--- .../net/helenus/core/cache/GuavaCache.java | 43 ------ .../net/helenus/core/cache/SessionCache.java | 60 -------- 5 files changed, 112 insertions(+), 184 deletions(-) delete mode 100644 src/main/java/net/helenus/core/cache/GuavaCache.java delete mode 100644 src/main/java/net/helenus/core/cache/SessionCache.java diff --git a/pom.xml b/pom.xml index 8c11457..c1a88e5 100644 --- a/pom.xml +++ b/pom.xml @@ -112,6 +112,12 @@ 3.3.2 + + com.datastax.cassandra + cassandra-driver-extras + 3.3.2 + + com.diffplug.durian durian @@ -136,12 +142,24 @@ 4.3.10.RELEASE + + javax.cache + cache-api + 1.1.0 + + com.google.guava guava 20.0 + + ca.exprofesso + guava-jcache + 1.0.4 + + io.zipkin.java @@ -259,7 +277,6 @@ 1.7.1 runtime - diff --git a/src/main/java/net/helenus/core/HelenusSession.java b/src/main/java/net/helenus/core/HelenusSession.java index 79ef069..76f3509 100644 --- a/src/main/java/net/helenus/core/HelenusSession.java +++ b/src/main/java/net/helenus/core/HelenusSession.java @@ -15,25 +15,12 @@ */ package net.helenus.core; -import static net.helenus.core.Query.eq; - import brave.Tracer; import com.codahale.metrics.MetricRegistry; import com.datastax.driver.core.*; import com.google.common.collect.Table; -import java.io.Closeable; -import java.io.PrintStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.concurrent.Executor; -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import net.helenus.core.cache.CacheUtil; import net.helenus.core.cache.Facet; -import net.helenus.core.cache.SessionCache; import net.helenus.core.cache.UnboundFacet; import net.helenus.core.operation.*; import net.helenus.core.reflect.Drafted; @@ -50,6 +37,24 @@ import net.helenus.support.Fun.Tuple6; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.cache.Cache; +import javax.cache.CacheManager; +import javax.cache.Caching; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.spi.CachingProvider; +import java.io.Closeable; +import java.io.PrintStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.concurrent.Executor; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static net.helenus.core.Query.eq; + public class HelenusSession extends AbstractSessionOperations implements Closeable { public static final Object deleted = new Object(); @@ -68,7 +73,7 @@ public class HelenusSession extends AbstractSessionOperations implements Closeab private final SessionRepository sessionRepository; private final Executor executor; private final boolean dropSchemaOnClose; - private final SessionCache sessionCache; + private final CacheManager cacheManager; private final RowColumnValueProvider valueProvider; private final StatementColumnValuePreparer valuePreparer; private final Metadata metadata; @@ -77,21 +82,21 @@ public class HelenusSession extends AbstractSessionOperations implements Closeab private volatile boolean showValues; HelenusSession( - Session session, - String usingKeyspace, - CodecRegistry registry, - boolean showCql, - boolean showValues, - PrintStream printStream, - SessionRepositoryBuilder sessionRepositoryBuilder, - Executor executor, - boolean dropSchemaOnClose, - ConsistencyLevel consistencyLevel, - boolean defaultQueryIdempotency, - Class unitOfWorkClass, - SessionCache sessionCache, - MetricRegistry metricRegistry, - Tracer tracer) { + Session session, + String usingKeyspace, + CodecRegistry registry, + boolean showCql, + boolean showValues, + PrintStream printStream, + SessionRepositoryBuilder sessionRepositoryBuilder, + Executor executor, + boolean dropSchemaOnClose, + ConsistencyLevel consistencyLevel, + boolean defaultQueryIdempotency, + Class unitOfWorkClass, + CacheManager cacheManager, + MetricRegistry metricRegistry, + Tracer tracer) { this.session = session; this.registry = registry == null ? CodecRegistry.DEFAULT_INSTANCE : registry; this.usingKeyspace = @@ -109,11 +114,14 @@ public class HelenusSession extends AbstractSessionOperations implements Closeab this.unitOfWorkClass = unitOfWorkClass; this.metricRegistry = metricRegistry; this.zipkinTracer = tracer; + this.cacheManager = cacheManger; - if (sessionCache == null) { - this.sessionCache = SessionCache.defaultCache(); - } else { - this.sessionCache = sessionCache; + if (cacheManager == null) { + MutableConfiguration configuration = new MutableConfiguration<>(); + configuration.setStoreByValue(false); + configuration.setTypes(String.class, Object.class); + CachingProvider cachingProvider = Caching.getCachingProvider(GuavaCacheManager.class.getName()); + cacheManager = cachingProvider.getCacheManager(); } this.valueProvider = new RowColumnValueProvider(this.sessionRepository); @@ -214,10 +222,13 @@ public class HelenusSession extends AbstractSessionOperations implements Closeab @Override public Object checkCache(String tableName, List facets) { Object result = null; - for (String key : CacheUtil.flatKeys(tableName, facets)) { - result = sessionCache.get(key); - if (result != null) { - return result; + Cache cache = cacheManager.getCache(tableName); + if (cache != null) { + for (String key : CacheUtil.flatKeys(tableName, facets)) { + result = cache.get(key); + if (result != null) { + return result; + } } } return null; @@ -226,7 +237,10 @@ public class HelenusSession extends AbstractSessionOperations implements Closeab @Override public void cacheEvict(List facets) { String tableName = CacheUtil.schemaName(facets); - CacheUtil.flatKeys(tableName, facets).forEach(key -> sessionCache.invalidate(key)); + Cache cache = cacheManager.getCache(tableName); + if (cache != null) { + CacheUtil.flatKeys(tableName, facets).forEach(key -> cache.remove(key)); + } } @Override @@ -278,6 +292,7 @@ public class HelenusSession extends AbstractSessionOperations implements Closeab pojo instanceof MapExportable ? ((MapExportable) pojo).toMap() : null; if (entity.isCacheable()) { List boundFacets = new ArrayList<>(); + String tableName = CacheUtil.schemaName(boundFacets); for (Facet facet : entity.getFacets()) { if (facet instanceof UnboundFacet) { UnboundFacet unboundFacet = (UnboundFacet) facet; @@ -305,34 +320,43 @@ public class HelenusSession extends AbstractSessionOperations implements Closeab } } List facetCombinations = CacheUtil.flattenFacets(boundFacets); - String tableName = CacheUtil.schemaName(boundFacets); replaceCachedFacetValues(pojo, tableName, facetCombinations); } } - List> deletedFacetSets = - uowCache - .values() - .stream() - .filter(Either::isRight) - .map(Either::getRight) - .collect(Collectors.toList()); - for (List facets : deletedFacetSets) { - String tableName = CacheUtil.schemaName(facets); - List keys = CacheUtil.flatKeys(tableName, facets); - keys.forEach(key -> sessionCache.invalidate(key)); - } + if (cacheManager != null) { + List> deletedFacetSets = + uowCache + .values() + .stream() + .filter(Either::isRight) + .map(Either::getRight) + .collect(Collectors.toList()); + for (List facets : deletedFacetSets) { + String tableName = CacheUtil.schemaName(facets); + Cache cache = cacheManager.getCache(tableName); + if (cache != null) { + List keys = CacheUtil.flatKeys(tableName, facets); + keys.forEach(key -> cache.remove(key)); + } + } + } } private void replaceCachedFacetValues( Object pojo, String tableName, List facetCombinations) { for (String[] combination : facetCombinations) { - String cacheKey = tableName + "." + Arrays.toString(combination); - if (pojo == null || pojo == HelenusSession.deleted) { - sessionCache.invalidate(cacheKey); - } else { - sessionCache.put(cacheKey, pojo); - } + String cacheKey = tableName + "." + Arrays.toString(combination); + if (cacheManager != null) { + Cache cache = cacheManager.getCache(tableName); + if (cache != null) { + if (pojo == null || pojo == HelenusSession.deleted) { + cache.remove(cacheKey); + } else { + cache.put(cacheKey, pojo); + } + } + } } } diff --git a/src/main/java/net/helenus/core/SessionInitializer.java b/src/main/java/net/helenus/core/SessionInitializer.java index 5904494..26c921b 100644 --- a/src/main/java/net/helenus/core/SessionInitializer.java +++ b/src/main/java/net/helenus/core/SessionInitializer.java @@ -17,26 +17,8 @@ package net.helenus.core; import brave.Tracer; import com.codahale.metrics.MetricRegistry; -import com.datastax.driver.core.CodecRegistry; -import com.datastax.driver.core.ConsistencyLevel; -import com.datastax.driver.core.KeyspaceMetadata; -import com.datastax.driver.core.Session; -import com.datastax.driver.core.TableMetadata; -import com.datastax.driver.core.UserType; +import com.datastax.driver.core.*; import com.google.common.util.concurrent.MoreExecutors; -import java.io.IOException; -import java.io.PrintStream; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.function.Consumer; -import net.helenus.core.cache.SessionCache; import net.helenus.core.reflect.DslExportable; import net.helenus.mapping.HelenusEntity; import net.helenus.mapping.HelenusEntityType; @@ -47,6 +29,14 @@ import net.helenus.support.Either; import net.helenus.support.HelenusException; import net.helenus.support.PackageUtil; +import javax.cache.CacheManager; +import java.io.IOException; +import java.io.PrintStream; +import java.util.*; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.function.Consumer; + public final class SessionInitializer extends AbstractSessionOperations { private final Session session; @@ -67,7 +57,7 @@ public final class SessionInitializer extends AbstractSessionOperations { private boolean dropUnusedIndexes = false; private KeyspaceMetadata keyspaceMetadata; private AutoDdl autoDdl = AutoDdl.UPDATE; - private SessionCache sessionCache = null; + private CacheManager cacheManager = null; SessionInitializer(Session session, String keyspace) { this.session = session; @@ -157,8 +147,8 @@ public final class SessionInitializer extends AbstractSessionOperations { return this; } - public SessionInitializer setSessionCache(SessionCache sessionCache) { - this.sessionCache = sessionCache; + public SessionInitializer setCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; return this; } @@ -304,7 +294,7 @@ public final class SessionInitializer extends AbstractSessionOperations { consistencyLevel, idempotent, unitOfWorkClass, - sessionCache, + cacheManager, metricRegistry, zipkinTracer); } diff --git a/src/main/java/net/helenus/core/cache/GuavaCache.java b/src/main/java/net/helenus/core/cache/GuavaCache.java deleted file mode 100644 index 5418c3a..0000000 --- a/src/main/java/net/helenus/core/cache/GuavaCache.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2015 The Helenus Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.helenus.core.cache; - -import com.google.common.cache.Cache; - -public class GuavaCache implements SessionCache { - - final Cache cache; - - GuavaCache(Cache cache) { - this.cache = cache; - } - - @Override - public void invalidate(K key) { - cache.invalidate(key); - } - - @Override - public V get(K key) { - return cache.getIfPresent(key); - } - - @Override - public void put(K key, V value) { - cache.put(key, value); - } -} diff --git a/src/main/java/net/helenus/core/cache/SessionCache.java b/src/main/java/net/helenus/core/cache/SessionCache.java deleted file mode 100644 index 4b6d8d0..0000000 --- a/src/main/java/net/helenus/core/cache/SessionCache.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015 The Helenus Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.helenus.core.cache; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; -import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public interface SessionCache { - - static final Logger LOG = LoggerFactory.getLogger(SessionCache.class); - - static SessionCache defaultCache() { - GuavaCache cache; - RemovalListener listener = - new RemovalListener() { - @Override - public void onRemoval(RemovalNotification n) { - if (n.wasEvicted()) { - String cause = n.getCause().name(); - LOG.info(cause); - } - } - }; - - cache = - new GuavaCache( - CacheBuilder.newBuilder() - .maximumSize(25_000) - .expireAfterAccess(5, TimeUnit.MINUTES) - .softValues() - .removalListener(listener) - .build()); - - return cache; - } - - void invalidate(K key); - - V get(K key); - - void put(K key, V value); -}