hazelcast cashing map
This commit is contained in:
parent
7652e28ae9
commit
e6e4449b7f
12 changed files with 304 additions and 3 deletions
|
|
@ -0,0 +1,42 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import java.util.Optional;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
||||
|
||||
public class ImdgHazelcastCashingV2<T extends SpcexObjectBase, K> extends ImdgHazelcast<T> {
|
||||
private final CashV2<Long, T> idCash;
|
||||
|
||||
public ImdgHazelcastCashingV2(CashV2<Long, T> idCash) {
|
||||
this.idCash = idCash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getSingleObjectByID(Long paramLong) {
|
||||
if (idCash == null) {
|
||||
return super.getSingleObjectByID(paramLong);
|
||||
}
|
||||
Optional<T> obj = idCash.getOrFind(paramLong, () -> super.getSingleObjectByID(paramLong));
|
||||
return obj.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getSingleObjectByPredicate(ImdgPredicate predicate) {
|
||||
if (!predicate.isCashing()) {
|
||||
return super.getSingleObjectByPredicate(predicate);
|
||||
}
|
||||
ImdgPredicateHazelcastCashing<?, T> casted = (ImdgPredicateHazelcastCashing<?, T>) predicate;
|
||||
Optional<T> obj = casted.getOrFind(() -> super.getSingleObjectByPredicate(predicate));
|
||||
return obj.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getFirstObjectByPredicate(ImdgPredicate predicate) {
|
||||
if (!predicate.isCashing()) {
|
||||
return super.getFirstObjectByPredicate(predicate);
|
||||
}
|
||||
ImdgPredicateHazelcastCashing<?, T> casted = (ImdgPredicateHazelcastCashing<?, T>) predicate;
|
||||
Optional<T> obj = casted.getOrFind(() -> super.getFirstObjectByPredicate(predicate));
|
||||
return obj.orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import com.hazelcast.query.Predicate;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.predicate.ImdgPredicateHazelcast;
|
||||
|
||||
public class ImdgPredicateHazelcastCashing<K, T> extends ImdgPredicateHazelcast {
|
||||
|
||||
private final CashV2<K, T> cash;
|
||||
private final K key;
|
||||
|
||||
public ImdgPredicateHazelcastCashing(Predicate hazelcastPredicate,
|
||||
CashV2<K, T> cash,
|
||||
K key) {
|
||||
super(hazelcastPredicate); //prdct.getRawPredicate()
|
||||
this.cash = cash;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCashing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected K key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public Optional<T> getOrFind(Supplier<T> supplier) {
|
||||
K key = key();
|
||||
return cash.getOrFind(key, supplier);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,8 @@ import com.hazelcast.query.Predicates;
|
|||
import com.hazelcast.query.SqlPredicate;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgPredicateHazelcastCashing;
|
||||
|
||||
public class ImdgPredicateBuilderHazelcast implements ImdgPredicateBuilder {
|
||||
protected static final ImdgPredicateBuilderHazelcast instance = new ImdgPredicateBuilderHazelcast();
|
||||
|
|
@ -117,4 +119,10 @@ public class ImdgPredicateBuilderHazelcast implements ImdgPredicateBuilder {
|
|||
public ImdgPredicate alwaysFalse() {
|
||||
return new ImdgPredicateHazelcast(Predicates.alwaysFalse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> ImdgPredicate cashed(ImdgPredicate prdct, CashV2<K, V> cash, K key) {
|
||||
Predicate rawPredicate = ((ImdgPredicateHazelcast) prdct).getRawPredicate();
|
||||
return new ImdgPredicateHazelcastCashing<>(rawPredicate, cash, key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import com.hazelcast.client.HazelcastClient;
|
||||
import com.hazelcast.client.config.ClientConfig;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
|
@ -16,16 +22,15 @@ import ru.spcex.platform.imdg.api.Imdg;
|
|||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.ImdgTransaction;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcastCashingV2;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgIdGeneratorHazelcast;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgTransactionProviderHazelcast;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public abstract class HazelcastServiceBase
|
||||
// implements IHazelcastService
|
||||
implements ImdgProvider
|
||||
|
|
@ -242,6 +247,26 @@ public abstract class HazelcastServiceBase
|
|||
return imdg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends SpcexObjectBase> Imdg<T> getCashingImdg(String key, Class<T> clazz, CashV2<Long, T> idCash) {
|
||||
ImdgHazelcast<T> imdg = new ImdgHazelcastCashingV2<>(idCash);
|
||||
statusSubscribe(new IHazelcastClusterStatus() {
|
||||
@Override
|
||||
public void getAvailable(HazelcastInstance hazelcastNotInited) {
|
||||
IdGenerator generator = hazelcastInstance.getIdGenerator(IMDGDistributedNames.MAP_SEQUENCE_NAME);
|
||||
imdg.setMap(hazelcastInstance.getMap(key));
|
||||
imdg.setMapName(key);
|
||||
imdg.setHzInstance(hazelcastInstance);
|
||||
imdg.setIdGenerator(generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getUnavailable(HazelcastInstance hazelcastNotInited) {
|
||||
}
|
||||
});
|
||||
return imdg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void waitAvailable() {
|
||||
if (lockAvailable == null) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@
|
|||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-utils</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package ru.spcex.platform.imdg.api;
|
||||
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
|
||||
|
||||
public interface ImdgProvider {
|
||||
/**
|
||||
|
|
@ -8,6 +9,13 @@ public interface ImdgProvider {
|
|||
*/
|
||||
<T extends SpcexObjectBase> Imdg<T> getImdg(String key, Class<T> clazz);
|
||||
|
||||
/**
|
||||
* idCash can be null
|
||||
*/
|
||||
default <T extends SpcexObjectBase> Imdg<T> getCashingImdg(String key, Class<T> clazz, CashV2<Long, T> idCash) {
|
||||
return getImdg(key, clazz);
|
||||
}
|
||||
|
||||
ImdgId getImdgIdGenerator();
|
||||
|
||||
ImdgTransaction newTransaction();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
package ru.spcex.platform.imdg.api.predicate;
|
||||
|
||||
public interface ImdgPredicate {
|
||||
default boolean isCashing() {return false;}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package ru.spcex.platform.imdg.api.predicate;
|
||||
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
|
||||
|
||||
public interface ImdgPredicateBuilder {
|
||||
ImdgPredicate equals(String key, Object value);
|
||||
ImdgPredicate greatEqual(String key, Comparable value);
|
||||
|
|
@ -23,4 +25,7 @@ public interface ImdgPredicateBuilder {
|
|||
|
||||
ImdgPredicate alwaysTrue();
|
||||
ImdgPredicate alwaysFalse();
|
||||
default <K, V> ImdgPredicate cashed(ImdgPredicate prdct, CashV2<K, V> cash, K key) {
|
||||
return prdct;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class CashCloser implements AutoCloseable {
|
||||
protected Collection<CashV2<?, ?>> cashes;
|
||||
|
||||
public CashCloser(CashV2<?, ?>... cashes) {
|
||||
this.cashes = List.of(cashes);
|
||||
}
|
||||
|
||||
public CashCloser() {}
|
||||
|
||||
public CashCloser add(CashV2<?, ?> cash) {
|
||||
this.cashes.add(cash);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
cashes.forEach(CashV2::clear);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class CashV2<K, T> {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private long hitRate = 0;
|
||||
private long missRate = 0;
|
||||
private final Map<K, T> cash;
|
||||
private final String name;
|
||||
|
||||
public CashV2() {
|
||||
this.cash = new HashMap<>();
|
||||
this.name = null;
|
||||
}
|
||||
|
||||
public CashV2(String name) {
|
||||
this.cash = new HashMap<>();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
log.info("cash {}: size {}, hit rate {}, miss rate {}",
|
||||
name != null ? name : "[unknown]",
|
||||
cash.size(),
|
||||
hitRate,
|
||||
missRate);
|
||||
this.hitRate = 0L;
|
||||
this.missRate = 0L;
|
||||
this.cash.clear();
|
||||
}
|
||||
|
||||
public void store(T obj) {
|
||||
if (obj == null || !needToStore(obj)) return;
|
||||
K key = extractKey(obj);
|
||||
cash.put(key, obj);
|
||||
}
|
||||
|
||||
protected Optional<T> get(K key) {
|
||||
T obj = cash.get(key);
|
||||
if (obj != null) hitRate++;
|
||||
else missRate++;
|
||||
return Optional.ofNullable(obj);
|
||||
}
|
||||
|
||||
protected Optional<T> getOrFind(K key, Supplier<T> supplier) {
|
||||
Optional<T> by = get(key);
|
||||
if (by.isEmpty()) {
|
||||
T t = supplier.get();
|
||||
if (t != null && needToStore(t)) {
|
||||
cash.put(key, t);
|
||||
by = Optional.of(t);
|
||||
}
|
||||
}
|
||||
return by;
|
||||
}
|
||||
|
||||
protected Optional<T> getOrFindO(K key, Supplier<Optional<T>> supplier) {
|
||||
Optional<T> fromCash = get(key);
|
||||
if (fromCash.isEmpty()) {
|
||||
Optional<T> foundAnew = supplier.get();
|
||||
if (foundAnew.isPresent()) {
|
||||
if (needToStore(foundAnew.get())) {
|
||||
cash.put(key, foundAnew.get());
|
||||
}
|
||||
fromCash = foundAnew;
|
||||
}
|
||||
}
|
||||
return fromCash;
|
||||
}
|
||||
|
||||
protected abstract K extractKey(T obj);
|
||||
|
||||
protected boolean needToStore(T obj) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
|
||||
public class CashV2ById<T extends SpcexObjectBase> extends CashV2<Long, T> {
|
||||
|
||||
public CashV2ById() {
|
||||
}
|
||||
|
||||
public CashV2ById(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> getOrFind(Long key, Supplier<T> supplier) {
|
||||
return super.getOrFind(key, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> get(Long key) {
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long extractKey(T obj) {
|
||||
return obj.getId();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class CashV2ByString<T> extends CashV2<String, T> {
|
||||
|
||||
private final Function<T, String> codeExtractor;
|
||||
|
||||
public CashV2ByString(Function<T, String> codeExtractor) {
|
||||
this.codeExtractor = codeExtractor;
|
||||
}
|
||||
|
||||
public CashV2ByString(String name, Function<T, String> codeExtractor) {
|
||||
super(name);
|
||||
this.codeExtractor = codeExtractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> getOrFind(String key, Supplier<T> supplier) {
|
||||
return super.getOrFind(key, supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> get(String key) {
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String extractKey(T obj) {
|
||||
return codeExtractor.apply(obj);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue