mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-10-14 22:17:50 +00:00
feat[cache]: batch remove callback
This commit is contained in:
1 parent
c91e4f6f08
commit
db7feb2acf
3 files changed
+22
-46
No files matched your search
+3
-31
@@ -72,39 +72,13 @@ public class EntityCache<PK extends Comparable<PK>, E extends IEntity<PK>> imple
|
|||||||
wrapper = EnhanceUtils.createEntityWrapper(entityWrapper);
|
wrapper = EnhanceUtils.createEntityWrapper(entityWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeCallback = new BiConsumer<Pair<PK, PNode<PK, E>>, LazyCache.RemovalCause>() {
|
var removeCallback = new BiConsumer<List<Pair<PK, PNode<PK, E>>>, LazyCache.RemovalCause>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(Pair<PK, PNode<PK, E>> pair, LazyCache.RemovalCause removalCause) {
|
public void accept(List<Pair<PK, PNode<PK, E>>> removes, LazyCache.RemovalCause removalCause) {
|
||||||
if (removalCause == LazyCache.RemovalCause.EXPLICIT) {
|
if (removalCause == LazyCache.RemovalCause.EXPLICIT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
EventBus.asyncExecute(clazz.hashCode(), () -> doPersist(removes.stream().map(it -> it.getValue().getEntity()).toList()));
|
||||||
var pk = pair.getKey();
|
|
||||||
var pnode = pair.getValue();
|
|
||||||
if (pnode.getWriteToDbTime() == pnode.getModifiedTime()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存失效之前,将数据写入数据库
|
|
||||||
var entity = pnode.getEntity();
|
|
||||||
EventBus.asyncExecute(clazz.hashCode(), new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
var collection = OrmContext.getOrmManager().getCollection(clazz);
|
|
||||||
|
|
||||||
var version = wrapper.gvs(entity);
|
|
||||||
wrapper.svs(entity, version + 1);
|
|
||||||
|
|
||||||
var filter = wrapper.gvs(entity) > 0
|
|
||||||
? Filters.and(Filters.eq("_id", entity.id()), Filters.eq(wrapper.versionFieldName(), version))
|
|
||||||
: Filters.eq("_id", entity.id());
|
|
||||||
var result = collection.replaceOne(filter, entity);
|
|
||||||
if (result.getMatchedCount() <= 0) {
|
|
||||||
// 移除缓存时,更新数据库中的实体文档异常
|
|
||||||
logger.error("onRemoval(): update entity to db failed when remove [{}] [pk:{}] by [removalCause:{}]", clazz.getSimpleName(), entity.id(), removalCause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var expireCheckIntervalMillis = Math.max(3 * TimeUtils.MILLIS_PER_SECOND, entityDef.getExpireMillisecond() / 10);
|
var expireCheckIntervalMillis = Math.max(3 * TimeUtils.MILLIS_PER_SECOND, entityDef.getExpireMillisecond() / 10);
|
||||||
@@ -353,8 +327,6 @@ public class EntityCache<PK extends Comparable<PK>, E extends IEntity<PK>> imple
|
|||||||
}
|
}
|
||||||
persistAllAndCompare(currentUpdateList);
|
persistAllAndCompare(currentUpdateList);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateList.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void persistAllAndCompare(List<E> updateList) {
|
private void persistAllAndCompare(List<E> updateList) {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.zfoo.scheduler.util;
|
package com.zfoo.scheduler.util;
|
||||||
|
|
||||||
import com.zfoo.protocol.model.Pair;
|
import com.zfoo.protocol.model.Pair;
|
||||||
import com.zfoo.protocol.model.PairLong;
|
|
||||||
import com.zfoo.protocol.util.AssertionUtils;
|
import com.zfoo.protocol.util.AssertionUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
@@ -59,10 +59,10 @@ public class LazyCache<K, V> {
|
|||||||
private volatile long minExpireTime;
|
private volatile long minExpireTime;
|
||||||
private AtomicLong expireCheckTimeAtomic;
|
private AtomicLong expireCheckTimeAtomic;
|
||||||
private ConcurrentMap<K, CacheValue<V>> cacheMap;
|
private ConcurrentMap<K, CacheValue<V>> cacheMap;
|
||||||
private BiConsumer<Pair<K, V>, RemovalCause> removeListener = (pair, removalCause) -> {
|
private BiConsumer<List<Pair<K, V>>, RemovalCause> removeListener = (removes, removalCause) -> {
|
||||||
};
|
};
|
||||||
|
|
||||||
public LazyCache(int maximumSize, long expireAfterAccessMillis, long expireCheckIntervalMillis, BiConsumer<Pair<K, V>, RemovalCause> removeListener) {
|
public LazyCache(int maximumSize, long expireAfterAccessMillis, long expireCheckIntervalMillis, BiConsumer<List<Pair<K, V>>, RemovalCause> removeListener) {
|
||||||
AssertionUtils.ge1(maximumSize);
|
AssertionUtils.ge1(maximumSize);
|
||||||
AssertionUtils.ge0(expireAfterAccessMillis);
|
AssertionUtils.ge0(expireAfterAccessMillis);
|
||||||
AssertionUtils.ge0(expireCheckIntervalMillis);
|
AssertionUtils.ge0(expireCheckIntervalMillis);
|
||||||
@@ -87,7 +87,7 @@ public class LazyCache<K, V> {
|
|||||||
cacheValue.expireTime = TimeUtils.now() + expireAfterAccessMillis;
|
cacheValue.expireTime = TimeUtils.now() + expireAfterAccessMillis;
|
||||||
var oldCacheValue = cacheMap.put(key, cacheValue);
|
var oldCacheValue = cacheMap.put(key, cacheValue);
|
||||||
if (oldCacheValue != null) {
|
if (oldCacheValue != null) {
|
||||||
removeListener.accept(new Pair<>(key, oldCacheValue.value), RemovalCause.REPLACED);
|
removeListener.accept(List.of(new Pair<>(key, oldCacheValue.value)), RemovalCause.REPLACED);
|
||||||
}
|
}
|
||||||
checkExpire();
|
checkExpire();
|
||||||
checkMaximumSize();
|
checkMaximumSize();
|
||||||
@@ -119,7 +119,7 @@ public class LazyCache<K, V> {
|
|||||||
}
|
}
|
||||||
var cacheValue = cacheMap.remove(key);
|
var cacheValue = cacheMap.remove(key);
|
||||||
if (cacheValue != null) {
|
if (cacheValue != null) {
|
||||||
removeListener.accept(new Pair<>(key, cacheValue.value), removalCause);
|
removeListener.accept(List.of(new Pair<>(key, cacheValue.value)), removalCause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,12 +137,13 @@ public class LazyCache<K, V> {
|
|||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
private void checkMaximumSize() {
|
private void checkMaximumSize() {
|
||||||
if (cacheMap.size() > backPressureSize) {
|
if (cacheMap.size() > backPressureSize) {
|
||||||
cacheMap.entrySet()
|
var removeList = cacheMap.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.map(it -> new PairLong<>(it.getValue().expireTime, it.getKey()))
|
.sorted((a, b) -> Long.compare(a.getValue().expireTime, b.getValue().expireTime))
|
||||||
.sorted((a, b) -> Long.compare(a.getKey(), b.getKey()))
|
|
||||||
.limit(Math.max(0, cacheMap.size() - maximumSize))
|
.limit(Math.max(0, cacheMap.size() - maximumSize))
|
||||||
.forEach(it -> removeForCause(it.getValue(), RemovalCause.SIZE));
|
.map(it -> new Pair<>(it.getKey(), it.getValue().value))
|
||||||
|
.toList();
|
||||||
|
removeListener.accept(removeList, RemovalCause.SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,18 +154,18 @@ public class LazyCache<K, V> {
|
|||||||
if (expireCheckTimeAtomic.compareAndSet(expireCheckTime, now + expireCheckIntervalMillis)) {
|
if (expireCheckTimeAtomic.compareAndSet(expireCheckTime, now + expireCheckIntervalMillis)) {
|
||||||
if (now > this.minExpireTime) {
|
if (now > this.minExpireTime) {
|
||||||
var minTimestamp = Long.MAX_VALUE;
|
var minTimestamp = Long.MAX_VALUE;
|
||||||
var removeList = new ArrayList<K>();
|
var removeList = new ArrayList<Pair<K, V>>();
|
||||||
for (var entry : cacheMap.entrySet()) {
|
for (var entry : cacheMap.entrySet()) {
|
||||||
var expireTime = entry.getValue().expireTime;
|
var expireTime = entry.getValue().expireTime;
|
||||||
if (expireTime < now) {
|
if (expireTime < now) {
|
||||||
removeList.add(entry.getKey());
|
removeList.add(new Pair<>(entry.getKey(), entry.getValue().value));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (expireTime < minTimestamp) {
|
if (expireTime < minTimestamp) {
|
||||||
minTimestamp = expireTime;
|
minTimestamp = expireTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeList.forEach(it -> removeForCause(it, RemovalCause.EXPIRED));
|
removeListener.accept(removeList, RemovalCause.EXPIRED);
|
||||||
if (this.minExpireTime < Long.MAX_VALUE) {
|
if (this.minExpireTime < Long.MAX_VALUE) {
|
||||||
this.minExpireTime = minTimestamp;
|
this.minExpireTime = minTimestamp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.junit.Test;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
@@ -19,10 +20,12 @@ public class LazyCacheTesting {
|
|||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(LazyCacheTesting.class);
|
private static final Logger logger = LoggerFactory.getLogger(LazyCacheTesting.class);
|
||||||
|
|
||||||
private static final BiConsumer<Pair<Integer, String>, LazyCache.RemovalCause> myRemoveCallback = new BiConsumer<Pair<Integer, String>, LazyCache.RemovalCause>() {
|
private static final BiConsumer<List<Pair<Integer, String>>, LazyCache.RemovalCause> myRemoveCallback = new BiConsumer<List<Pair<Integer, String>>, LazyCache.RemovalCause>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(Pair<Integer, String> pair, LazyCache.RemovalCause removalCause) {
|
public void accept(List<Pair<Integer, String>> pairs, LazyCache.RemovalCause removalCause) {
|
||||||
logger.info("remove key:[{}] value:[{}] removalCause:[{}]", pair.getKey(), pair.getValue(), removalCause);
|
for(var pair : pairs) {
|
||||||
|
logger.info("remove key:[{}] value:[{}] removalCause:[{}]", pair.getKey(), pair.getValue(), removalCause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user