后台更新 服务优化
Build Backend JAR / build (push) Failing after 16m54s

This commit is contained in:
supernijia
2026-08-11 14:50:21 +08:00
parent 38216a1885
commit 5b1ccad40e
24 changed files with 1623 additions and 502 deletions
@@ -5,11 +5,17 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.nanri.aiimage.common.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@@ -29,6 +35,12 @@ public class ZiniaoTransientCacheService {
private final ConcurrentHashMap<String, Holder> map = new ConcurrentHashMap<>();
@Value("${aiimage.ziniao.transient-cache-max-entries:10000}")
private int maxEntries;
@Value("${aiimage.ziniao.transient-cache-max-payload-bytes:5242880}")
private int maxPayloadBytes;
public <T> Optional<T> get(String cacheType, String cacheKey, Class<T> valueType) {
Holder holder = getHolder(cacheType, cacheKey);
if (holder == null) {
@@ -68,8 +80,18 @@ public class ZiniaoTransientCacheService {
}
try {
String json = objectMapper.writeValueAsString(payload);
int payloadBytes = json.getBytes(StandardCharsets.UTF_8).length;
int payloadLimit = maxPayloadBytes > 0 ? maxPayloadBytes : 5 * 1024 * 1024;
if (payloadBytes > payloadLimit) {
log.warn("[ziniao-transient] skip oversized cache type={} keyLen={} bytes={} maxBytes={}",
normalizedType, normalizedKey.length(),
payloadBytes, payloadLimit);
return;
}
LocalDateTime expiresAt = LocalDateTime.now().plusSeconds(ttl.getSeconds());
cleanupExpiredEntries(LocalDateTime.now());
map.put(compoundKey(normalizedType, normalizedKey), new Holder(json, expiresAt));
evictToCapacity();
log.trace("[ziniao-transient] put type={} keyLen={} ttlSec={}", normalizedType, normalizedKey.length(), ttl.getSeconds());
} catch (Exception ex) {
throw new BusinessException("写入紫鸟进程缓存失败");
@@ -83,6 +105,36 @@ public class ZiniaoTransientCacheService {
log.trace("[ziniao-transient] delete type={}", normalizedType);
}
@Scheduled(fixedDelayString = "${aiimage.ziniao.transient-cache-cleanup-delay-ms:60000}")
void cleanupExpiredEntriesScheduled() {
cleanupExpiredEntries(LocalDateTime.now());
evictToCapacity();
}
private void cleanupExpiredEntries(LocalDateTime now) {
map.entrySet().removeIf(entry -> {
Holder holder = entry.getValue();
return holder == null || holder.expiresAt == null || !holder.expiresAt.isAfter(now);
});
}
private void evictToCapacity() {
int limit = maxEntries > 0 ? maxEntries : 10000;
int overflow = map.size() - limit;
if (overflow <= 0) {
return;
}
List<Map.Entry<String, Holder>> candidates = new ArrayList<>(map.entrySet());
candidates.sort(Comparator.comparing(entry -> entry.getValue().expiresAt,
Comparator.nullsFirst(Comparator.naturalOrder())));
candidates.stream().limit(overflow).forEach(entry ->
map.remove(entry.getKey(), entry.getValue()));
}
int size() {
return map.size();
}
private Holder getHolder(String cacheType, String cacheKey) {
String normalizedType = normalizeRequired(cacheType, "cacheType 不能为空");
String normalizedKey = normalizeRequired(cacheKey, "cacheKey 不能为空");