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 com.hazelcast.query.SqlPredicate;
|
||||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
||||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
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 {
|
public class ImdgPredicateBuilderHazelcast implements ImdgPredicateBuilder {
|
||||||
protected static final ImdgPredicateBuilderHazelcast instance = new ImdgPredicateBuilderHazelcast();
|
protected static final ImdgPredicateBuilderHazelcast instance = new ImdgPredicateBuilderHazelcast();
|
||||||
|
|
@ -117,4 +119,10 @@ public class ImdgPredicateBuilderHazelcast implements ImdgPredicateBuilder {
|
||||||
public ImdgPredicate alwaysFalse() {
|
public ImdgPredicate alwaysFalse() {
|
||||||
return new ImdgPredicateHazelcast(Predicates.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;
|
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.HazelcastClient;
|
||||||
import com.hazelcast.client.config.ClientConfig;
|
import com.hazelcast.client.config.ClientConfig;
|
||||||
import com.hazelcast.core.HazelcastInstance;
|
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.ImdgId;
|
||||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||||
import ru.spcex.platform.imdg.api.ImdgTransaction;
|
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.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.ImdgIdGeneratorHazelcast;
|
||||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgTransactionProviderHazelcast;
|
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.config.HazelcastClientParams;
|
||||||
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
|
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
|
||||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
public abstract class HazelcastServiceBase
|
public abstract class HazelcastServiceBase
|
||||||
// implements IHazelcastService
|
// implements IHazelcastService
|
||||||
implements ImdgProvider
|
implements ImdgProvider
|
||||||
|
|
@ -242,6 +247,26 @@ public abstract class HazelcastServiceBase
|
||||||
return imdg;
|
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
|
@Override
|
||||||
public synchronized void waitAvailable() {
|
public synchronized void waitAvailable() {
|
||||||
if (lockAvailable == null) {
|
if (lockAvailable == null) {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,14 @@
|
||||||
<groupId>ru.spcex.platform</groupId>
|
<groupId>ru.spcex.platform</groupId>
|
||||||
<artifactId>platform-utils</artifactId>
|
<artifactId>platform-utils</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package ru.spcex.platform.imdg.api;
|
package ru.spcex.platform.imdg.api;
|
||||||
|
|
||||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||||
|
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
|
||||||
|
|
||||||
public interface ImdgProvider {
|
public interface ImdgProvider {
|
||||||
/**
|
/**
|
||||||
|
|
@ -8,6 +9,13 @@ public interface ImdgProvider {
|
||||||
*/
|
*/
|
||||||
<T extends SpcexObjectBase> Imdg<T> getImdg(String key, Class<T> clazz);
|
<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();
|
ImdgId getImdgIdGenerator();
|
||||||
|
|
||||||
ImdgTransaction newTransaction();
|
ImdgTransaction newTransaction();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
package ru.spcex.platform.imdg.api.predicate;
|
package ru.spcex.platform.imdg.api.predicate;
|
||||||
|
|
||||||
public interface ImdgPredicate {
|
public interface ImdgPredicate {
|
||||||
|
default boolean isCashing() {return false;}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package ru.spcex.platform.imdg.api.predicate;
|
package ru.spcex.platform.imdg.api.predicate;
|
||||||
|
|
||||||
|
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
|
||||||
|
|
||||||
public interface ImdgPredicateBuilder {
|
public interface ImdgPredicateBuilder {
|
||||||
ImdgPredicate equals(String key, Object value);
|
ImdgPredicate equals(String key, Object value);
|
||||||
ImdgPredicate greatEqual(String key, Comparable value);
|
ImdgPredicate greatEqual(String key, Comparable value);
|
||||||
|
|
@ -23,4 +25,7 @@ public interface ImdgPredicateBuilder {
|
||||||
|
|
||||||
ImdgPredicate alwaysTrue();
|
ImdgPredicate alwaysTrue();
|
||||||
ImdgPredicate alwaysFalse();
|
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