task-32: 将 task entity 本地缓存替换为有容量和过期回收的实现
This commit is contained in:
@@ -7,6 +7,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ConfigurationProperties(prefix = "aiimage.task-pressure")
|
||||
public class TaskPressureProperties {
|
||||
private long localTaskEntityCacheMillis = 3000;
|
||||
/** task entity 本地缓存容量上限,超限时按时间戳 LRU 淘汰最旧条目。 */
|
||||
private int localTaskEntityCacheCapacity = 512;
|
||||
// 本地文件缓存有效时长,超过该时长视为过期、强制回查 DB,避免陈旧 RUNNING 被复活
|
||||
private long localTaskEntityFileCacheMillis = 60000;
|
||||
private int dbSelectBatchSize = 200;
|
||||
|
||||
+28
-1
@@ -13,6 +13,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -145,7 +146,7 @@ public class ShopDataCrawlTaskCacheService {
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
taskEntityLocalCache.put(task.getId(), new LocalTaskEntityCacheEntry(
|
||||
putLocalCache(task.getId(), new LocalTaskEntityCacheEntry(
|
||||
now,
|
||||
objectMapper.convertValue(task, FileTaskEntity.class)
|
||||
));
|
||||
@@ -159,6 +160,23 @@ public class ShopDataCrawlTaskCacheService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 有界本地缓存写入:容量达到上限时按 cachedAtMillis LRU 淘汰最旧条目,
|
||||
* 保证本地缓存内存有界。
|
||||
*/
|
||||
private void putLocalCache(Long taskId, LocalTaskEntityCacheEntry entry) {
|
||||
taskEntityLocalCache.put(taskId, entry);
|
||||
int capacity = Math.max(1, taskPressureProperties.getLocalTaskEntityCacheCapacity());
|
||||
if (taskEntityLocalCache.size() > capacity) {
|
||||
taskEntityLocalCache.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByValue(
|
||||
Comparator.comparingLong(LocalTaskEntityCacheEntry::cachedAtMillis)
|
||||
.thenComparingLong(e -> e.task() == null ? 0L : e.task().getId() == null ? 0L : e.task().getId())))
|
||||
.limit(taskEntityLocalCache.size() - capacity)
|
||||
.forEach(entryToEvict -> taskEntityLocalCache.remove(entryToEvict.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Long, FileTaskEntity> getTaskCacheBatch(java.util.List<Long> taskIds) {
|
||||
Map<Long, FileTaskEntity> result = new LinkedHashMap<>();
|
||||
if (taskIds == null || taskIds.isEmpty()) {
|
||||
@@ -178,6 +196,10 @@ public class ShopDataCrawlTaskCacheService {
|
||||
if (isLocalCacheFresh(cached, now)) {
|
||||
result.put(taskId, objectMapper.convertValue(cached.task(), FileTaskEntity.class));
|
||||
} else {
|
||||
// 过期条目即时回收,避免本地缓存无限累积。
|
||||
if (cached != null) {
|
||||
taskEntityLocalCache.remove(taskId);
|
||||
}
|
||||
missingIds.add(taskId);
|
||||
}
|
||||
}
|
||||
@@ -221,6 +243,11 @@ public class ShopDataCrawlTaskCacheService {
|
||||
&& now - cached.cachedAtMillis() <= Math.max(0L, taskPressureProperties.getLocalTaskEntityCacheMillis());
|
||||
}
|
||||
|
||||
/** 本地缓存当前条目数(测试与监控用)。 */
|
||||
int localCacheSize() {
|
||||
return taskEntityLocalCache.size();
|
||||
}
|
||||
|
||||
private record LocalTaskEntityCacheEntry(long cachedAtMillis, FileTaskEntity task) {}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user