WIP: Working toward a solution that can cache result sets and/or transformed entity instances when annotated with @Cacheable in the Session cache.
This commit is contained in:
parent
0fd9ff828c
commit
28aa3b1bae
17 changed files with 290 additions and 72 deletions
|
@ -220,7 +220,6 @@ public final class SessionInitializer extends AbstractSessionOperations {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void singleton() {
|
public void singleton() {
|
||||||
|
|
||||||
Helenus.setSession(get());
|
Helenus.setSession(get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,17 +20,17 @@ import java.util.concurrent.CompletableFuture;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
|
|
||||||
public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
public abstract class AbstractOperation<E, O extends AbstractOperation<E, O>>
|
||||||
extends AbstractStatementOperation<E, O> implements Transformational<E> {
|
extends AbstractStatementOperation<E, O> implements OperationsDelegate<E> {
|
||||||
|
|
||||||
public abstract E transform(ResultSet resultSet);
|
public abstract E transform(ResultSet resultSet);
|
||||||
|
|
||||||
|
protected CacheManager getCacheManager() { return null; }
|
||||||
|
|
||||||
public boolean cacheable() {
|
public boolean cacheable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCacheKey() {
|
public CacheKey getCacheKey() { return null; }
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.concurrent.CompletableFuture;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
|
|
||||||
public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOperation<E, O>>
|
public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOperation<E, O>>
|
||||||
extends AbstractStatementOperation<E, O> implements Transformational<Optional<E>> {
|
extends AbstractStatementOperation<E, O> implements OperationsDelegate<Optional<E>> {
|
||||||
|
|
||||||
public AbstractOptionalOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractOptionalOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
@ -33,6 +33,10 @@ public abstract class AbstractOptionalOperation<E, O extends AbstractOptionalOpe
|
||||||
|
|
||||||
public abstract Optional<E> transform(ResultSet resultSet);
|
public abstract Optional<E> transform(ResultSet resultSet);
|
||||||
|
|
||||||
|
protected CacheManager getCacheManager() { return null; }
|
||||||
|
|
||||||
|
public CacheKey getCacheKey() { return null; }
|
||||||
|
|
||||||
public PreparedOptionalOperation<E> prepare() {
|
public PreparedOptionalOperation<E> prepare() {
|
||||||
return new PreparedOptionalOperation<E>(prepareStatement(), this);
|
return new PreparedOptionalOperation<E>(prepareStatement(), this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.stream.Stream;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
|
|
||||||
public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperation<E, O>>
|
public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperation<E, O>>
|
||||||
extends AbstractStatementOperation<E, O> implements Transformational<Stream<E>> {
|
extends AbstractStatementOperation<E, O> implements OperationsDelegate<Stream<E>> {
|
||||||
|
|
||||||
public AbstractStreamOperation(AbstractSessionOperations sessionOperations) {
|
public AbstractStreamOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
@ -33,6 +33,10 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
|
|
||||||
public abstract Stream<E> transform(ResultSet resultSet);
|
public abstract Stream<E> transform(ResultSet resultSet);
|
||||||
|
|
||||||
|
protected CacheManager getCacheManager() { return null; }
|
||||||
|
|
||||||
|
public CacheKey getCacheKey() { return null; }
|
||||||
|
|
||||||
public PreparedStreamOperation<E> prepare() {
|
public PreparedStreamOperation<E> prepare() {
|
||||||
return new PreparedStreamOperation<E>(prepareStatement(), this);
|
return new PreparedStreamOperation<E>(prepareStatement(), this);
|
||||||
}
|
}
|
||||||
|
@ -51,11 +55,11 @@ public abstract class AbstractStreamOperation<E, O extends AbstractStreamOperati
|
||||||
|
|
||||||
public Stream<E> sync() {
|
public Stream<E> sync() {
|
||||||
return Executioner.INSTANCE.<Stream<E>>sync(
|
return Executioner.INSTANCE.<Stream<E>>sync(
|
||||||
sessionOps, options(buildStatement()), traceContext, this, showValues);
|
sessionOps, options(buildStatement()), getCacheManager(), traceContext, this, showValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Stream<E>> async() {
|
public CompletableFuture<Stream<E>> async() {
|
||||||
return Executioner.INSTANCE.<Stream<E>>async(
|
return Executioner.INSTANCE.<Stream<E>>async(
|
||||||
sessionOps, options(buildStatement()), traceContext, this, showValues);
|
sessionOps, options(buildStatement()), getCacheManager(), traceContext, this, showValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ public final class BoundOptionalOperation<E>
|
||||||
return delegate.transform(resultSet);
|
return delegate.transform(resultSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CacheKey getCacheKey() { return delegate.getCacheKey(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement buildStatement() {
|
public Statement buildStatement() {
|
||||||
return boundStatement;
|
return boundStatement;
|
||||||
|
|
|
@ -25,19 +25,27 @@ public final class BoundStreamOperation<E>
|
||||||
|
|
||||||
private final BoundStatement boundStatement;
|
private final BoundStatement boundStatement;
|
||||||
private final AbstractStreamOperation<E, ?> delegate;
|
private final AbstractStreamOperation<E, ?> delegate;
|
||||||
|
private final CacheKey cacheKey;
|
||||||
|
|
||||||
public BoundStreamOperation(
|
public BoundStreamOperation(
|
||||||
BoundStatement boundStatement, AbstractStreamOperation<E, ?> operation) {
|
BoundStatement boundStatement, CacheKey cacheKey, AbstractStreamOperation<E, ?> operation) {
|
||||||
super(operation.sessionOps);
|
super(operation.sessionOps);
|
||||||
this.boundStatement = boundStatement;
|
this.boundStatement = boundStatement;
|
||||||
|
this.cacheKey = cacheKey;
|
||||||
this.delegate = operation;
|
this.delegate = operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CacheManager getCacheManager() { return delegate.getCacheManager(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<E> transform(ResultSet resultSet) {
|
public Stream<E> transform(ResultSet resultSet) {
|
||||||
return delegate.transform(resultSet);
|
return delegate.transform(resultSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CacheKey getCacheKey() { return cacheKey; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement buildStatement() {
|
public Statement buildStatement() {
|
||||||
return boundStatement;
|
return boundStatement;
|
||||||
|
|
30
src/main/java/net/helenus/core/operation/CacheKey.java
Normal file
30
src/main/java/net/helenus/core/operation/CacheKey.java
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
public class CacheKey {
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
CacheKey() {}
|
||||||
|
|
||||||
|
CacheKey(String key) { this.key = key; }
|
||||||
|
|
||||||
|
public void set(String key) { this.key = key; }
|
||||||
|
|
||||||
|
public String toString() { return key; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
CacheKey cacheKey = (CacheKey) o;
|
||||||
|
|
||||||
|
return key.equals(cacheKey.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return key.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
src/main/java/net/helenus/core/operation/CacheManager.java
Normal file
49
src/main/java/net/helenus/core/operation/CacheManager.java
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import com.datastax.driver.core.ResultSetFuture;
|
||||||
|
import com.datastax.driver.core.Statement;
|
||||||
|
import net.helenus.mapping.HelenusEntity;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class CacheManager {
|
||||||
|
public enum Type { FETCH, MUTATE }
|
||||||
|
|
||||||
|
private static CacheManager sessionFetch = new SessionCacheManager(Type.FETCH);
|
||||||
|
|
||||||
|
protected CacheManager.Type type;
|
||||||
|
|
||||||
|
|
||||||
|
public static CacheManager of(Type type, HelenusEntity entity) {
|
||||||
|
if (entity != null && entity.isCacheable()) {
|
||||||
|
return sessionFetch;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheManager(Type type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ResultSet fetch(Statement statement, OperationsDelegate delegate, ResultSetFuture resultSetFuture)
|
||||||
|
throws InterruptedException, ExecutionException;
|
||||||
|
protected abstract ResultSet mutate(Statement statement, OperationsDelegate delegate, ResultSetFuture resultSetFuture)
|
||||||
|
throws InterruptedException, ExecutionException;
|
||||||
|
|
||||||
|
public ResultSet apply(Statement statement, OperationsDelegate delegate, ResultSetFuture futureResultSet)
|
||||||
|
throws InterruptedException, ExecutionException {
|
||||||
|
ResultSet resultSet = null;
|
||||||
|
switch (type) {
|
||||||
|
case FETCH:
|
||||||
|
resultSet = fetch(statement, delegate, futureResultSet);
|
||||||
|
break;
|
||||||
|
case MUTATE:
|
||||||
|
resultSet = mutate(statement, delegate, futureResultSet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import com.datastax.driver.core.ResultSet;
|
||||||
import com.datastax.driver.core.ResultSetFuture;
|
import com.datastax.driver.core.ResultSetFuture;
|
||||||
import com.datastax.driver.core.Statement;
|
import com.datastax.driver.core.Statement;
|
||||||
import net.helenus.core.AbstractSessionOperations;
|
import net.helenus.core.AbstractSessionOperations;
|
||||||
|
import net.helenus.support.HelenusException;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -18,12 +19,22 @@ public enum Executioner {
|
||||||
AbstractSessionOperations session,
|
AbstractSessionOperations session,
|
||||||
Statement statement,
|
Statement statement,
|
||||||
TraceContext traceContext,
|
TraceContext traceContext,
|
||||||
Transformational<E> delegate,
|
OperationsDelegate<E> delegate,
|
||||||
|
boolean showValues) {
|
||||||
|
return sync(session, statement, null, traceContext, delegate, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
<E> E sync(
|
||||||
|
AbstractSessionOperations session,
|
||||||
|
Statement statement,
|
||||||
|
CacheManager cacheManager,
|
||||||
|
TraceContext traceContext,
|
||||||
|
OperationsDelegate<E> delegate,
|
||||||
boolean showValues) {
|
boolean showValues) {
|
||||||
try {
|
try {
|
||||||
return this.<E>async(session, statement, traceContext, delegate, showValues).get();
|
return this.<E>async(session, statement, cacheManager, traceContext, delegate, showValues).get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
return null;
|
throw new HelenusException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,11 +42,21 @@ public enum Executioner {
|
||||||
AbstractSessionOperations session,
|
AbstractSessionOperations session,
|
||||||
Statement statement,
|
Statement statement,
|
||||||
TraceContext traceContext,
|
TraceContext traceContext,
|
||||||
Transformational<E> delegate,
|
OperationsDelegate<E> delegate,
|
||||||
|
boolean showValues) {
|
||||||
|
return async(session, statement, null, traceContext, delegate, showValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> CompletableFuture<E> async(
|
||||||
|
AbstractSessionOperations session,
|
||||||
|
Statement statement,
|
||||||
|
CacheManager cacheManager,
|
||||||
|
TraceContext traceContext,
|
||||||
|
OperationsDelegate<E> delegate,
|
||||||
boolean showValues) {
|
boolean showValues) {
|
||||||
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
ResultSetFuture futureResultSet = session.executeAsync(statement, showValues);
|
||||||
|
|
||||||
return CompletableFuture.supplyAsync(
|
return CompletableFuture.<E>supplyAsync(
|
||||||
() -> {
|
() -> {
|
||||||
Tracer tracer = session.getZipkinTracer();
|
Tracer tracer = session.getZipkinTracer();
|
||||||
final Span span =
|
final Span span =
|
||||||
|
@ -45,7 +66,8 @@ public enum Executioner {
|
||||||
span.name("cassandra");
|
span.name("cassandra");
|
||||||
span.start();
|
span.start();
|
||||||
}
|
}
|
||||||
ResultSet resultSet = futureResultSet.get(); // TODO: timeout
|
ResultSet resultSet = cacheManager != null ? cacheManager.apply(statement, delegate, futureResultSet) :
|
||||||
|
futureResultSet.get();
|
||||||
E result = delegate.transform(resultSet);
|
E result = delegate.transform(resultSet);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.helenus.core.operation;
|
||||||
|
|
||||||
import com.datastax.driver.core.ResultSet;
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
|
||||||
public interface Transformational<E> {
|
public interface OperationsDelegate<E> {
|
||||||
E transform(ResultSet resultSet);
|
E transform(ResultSet resultSet);
|
||||||
|
CacheKey getCacheKey();
|
||||||
}
|
}
|
|
@ -18,6 +18,8 @@ package net.helenus.core.operation;
|
||||||
import com.datastax.driver.core.BoundStatement;
|
import com.datastax.driver.core.BoundStatement;
|
||||||
import com.datastax.driver.core.PreparedStatement;
|
import com.datastax.driver.core.PreparedStatement;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class PreparedStreamOperation<E> {
|
public final class PreparedStreamOperation<E> {
|
||||||
|
|
||||||
private final PreparedStatement preparedStatement;
|
private final PreparedStatement preparedStatement;
|
||||||
|
@ -37,7 +39,10 @@ public final class PreparedStreamOperation<E> {
|
||||||
|
|
||||||
BoundStatement boundStatement = preparedStatement.bind(params);
|
BoundStatement boundStatement = preparedStatement.bind(params);
|
||||||
|
|
||||||
return new BoundStreamOperation<E>(boundStatement, operation);
|
String key = "use " + preparedStatement.getQueryKeyspace() + "; " + preparedStatement.getQueryString();
|
||||||
|
for (Object param : params) { key = key.replaceFirst(Pattern.quote("?"), param.toString()); }
|
||||||
|
|
||||||
|
return new BoundStreamOperation<E>(boundStatement, new CacheKey(key), operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -46,4 +46,5 @@ public final class SelectFirstOperation<E>
|
||||||
public Optional<E> transform(ResultSet resultSet) {
|
public Optional<E> transform(ResultSet resultSet) {
|
||||||
return src.transform(resultSet).findFirst();
|
return src.transform(resultSet).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
protected Integer limit = null;
|
protected Integer limit = null;
|
||||||
protected boolean allowFiltering = false;
|
protected boolean allowFiltering = false;
|
||||||
|
|
||||||
|
protected CacheManager cacheManager;
|
||||||
|
|
||||||
public SelectOperation(AbstractSessionOperations sessionOperations) {
|
public SelectOperation(AbstractSessionOperations sessionOperations) {
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
|
|
||||||
|
@ -67,6 +69,8 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
return (E) Fun.ArrayTuple.of(arr);
|
return (E) Fun.ArrayTuple.of(arr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.cacheManager = CacheManager.of(CacheManager.Type.FETCH, null) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
public SelectOperation(AbstractSessionOperations sessionOperations, HelenusEntity entity) {
|
||||||
|
@ -78,6 +82,8 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
.stream()
|
.stream()
|
||||||
.map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
.map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
||||||
.forEach(p -> this.props.add(p));
|
.forEach(p -> this.props.add(p));
|
||||||
|
|
||||||
|
this.cacheManager = CacheManager.of(CacheManager.Type.FETCH, entity) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectOperation(
|
public SelectOperation(
|
||||||
|
@ -93,6 +99,8 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
.stream()
|
.stream()
|
||||||
.map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
.map(p -> new HelenusPropertyNode(p, Optional.empty()))
|
||||||
.forEach(p -> this.props.add(p));
|
.forEach(p -> this.props.add(p));
|
||||||
|
|
||||||
|
this.cacheManager = CacheManager.of(CacheManager.Type.FETCH, entity) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectOperation(
|
public SelectOperation(
|
||||||
|
@ -103,6 +111,8 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
super(sessionOperations);
|
super(sessionOperations);
|
||||||
this.rowMapper = rowMapper;
|
this.rowMapper = rowMapper;
|
||||||
Collections.addAll(this.props, props);
|
Collections.addAll(this.props, props);
|
||||||
|
|
||||||
|
this.cacheManager = CacheManager.of(CacheManager.Type.FETCH, null) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CountOperation count() {
|
public CountOperation count() {
|
||||||
|
@ -252,6 +262,10 @@ public final class SelectOperation<E> extends AbstractFilterStreamOperation<E, S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected CacheManager getCacheManager() {
|
||||||
|
return cacheManager;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Ordering> getOrCreateOrdering() {
|
private List<Ordering> getOrCreateOrdering() {
|
||||||
if (ordering == null) {
|
if (ordering == null) {
|
||||||
ordering = new ArrayList<Ordering>();
|
ordering = new ArrayList<Ordering>();
|
||||||
|
|
|
@ -44,4 +44,5 @@ public final class SelectTransformingOperation<R, E>
|
||||||
public Stream<R> transform(ResultSet resultSet) {
|
public Stream<R> transform(ResultSet resultSet) {
|
||||||
return src.transform(resultSet).map(fn);
|
return src.transform(resultSet).map(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package net.helenus.core.operation;
|
||||||
|
|
||||||
|
import com.datastax.driver.core.ResultSet;
|
||||||
|
import com.datastax.driver.core.ResultSetFuture;
|
||||||
|
import com.datastax.driver.core.Statement;
|
||||||
|
import com.google.common.cache.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
|
public class SessionCacheManager extends CacheManager {
|
||||||
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private Cache<String, ResultSet> cache;
|
||||||
|
|
||||||
|
SessionCacheManager(CacheManager.Type type) {
|
||||||
|
super(type);
|
||||||
|
|
||||||
|
RemovalListener<String, ResultSet> listener;
|
||||||
|
listener = new RemovalListener<String, ResultSet>() {
|
||||||
|
@Override
|
||||||
|
public void onRemoval(RemovalNotification<String, ResultSet> n){
|
||||||
|
if (n.wasEvicted()) {
|
||||||
|
String cause = n.getCause().name();
|
||||||
|
logger.info(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cache = CacheBuilder.newBuilder()
|
||||||
|
.maximumSize(10_000)
|
||||||
|
.expireAfterAccess(20, TimeUnit.MINUTES)
|
||||||
|
.weakKeys()
|
||||||
|
.softValues()
|
||||||
|
.removalListener(listener)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ResultSet fetch(Statement statement, OperationsDelegate delegate, ResultSetFuture resultSetFuture)
|
||||||
|
throws InterruptedException, ExecutionException {
|
||||||
|
CacheKey key = delegate.getCacheKey();
|
||||||
|
final String cacheKey = key == null ? statement.toString() : key.toString();
|
||||||
|
ResultSet resultSet = null;
|
||||||
|
if (cacheKey == null) {
|
||||||
|
resultSet = resultSetFuture.get();
|
||||||
|
} else {
|
||||||
|
resultSet = cache.getIfPresent(cacheKey);
|
||||||
|
if (resultSet == null) {
|
||||||
|
resultSet = resultSetFuture.get();
|
||||||
|
if (resultSet != null) {
|
||||||
|
cache.put(cacheKey, resultSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ResultSet mutate(Statement statement, OperationsDelegate delegate, ResultSetFuture resultSetFuture)
|
||||||
|
throws InterruptedException, ExecutionException {
|
||||||
|
CacheKey key = delegate.getCacheKey();
|
||||||
|
final String cacheKey = key == null ? statement.toString() : key.toString();
|
||||||
|
ResultSet resultSet = resultSetFuture.get();
|
||||||
|
if (cacheKey != null && resultSet != null) {
|
||||||
|
cache.put(cacheKey, resultSet);
|
||||||
|
}
|
||||||
|
return resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,10 +16,13 @@
|
||||||
package net.helenus.test.integration.core.prepared;
|
package net.helenus.test.integration.core.prepared;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import net.helenus.core.annotation.Cacheable;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
|
||||||
@Table("cars")
|
@Table("cars")
|
||||||
|
@Cacheable
|
||||||
public interface Car {
|
public interface Car {
|
||||||
|
|
||||||
@PartitionKey(ordinal = 0)
|
@PartitionKey(ordinal = 0)
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package net.helenus.test.integration.core.simple;
|
package net.helenus.test.integration.core.simple;
|
||||||
|
|
||||||
|
import net.helenus.core.annotation.Cacheable;
|
||||||
import net.helenus.mapping.annotation.Column;
|
import net.helenus.mapping.annotation.Column;
|
||||||
import net.helenus.mapping.annotation.PartitionKey;
|
import net.helenus.mapping.annotation.PartitionKey;
|
||||||
import net.helenus.mapping.annotation.Table;
|
import net.helenus.mapping.annotation.Table;
|
||||||
|
|
||||||
@Table("simple_users")
|
@Table("simple_users")
|
||||||
|
@Cacheable
|
||||||
public interface User {
|
public interface User {
|
||||||
|
|
||||||
@PartitionKey
|
@PartitionKey
|
||||||
|
|
Loading…
Reference in a new issue