package com.wok.supportbot.cache; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; /** * AI 推荐问题(suggest-message-list)的内存缓存。 *
* key 为 chatId,value 为最近一次生成的 3 条建议问题。 * 不持久化到数据库——suggestions 是实时生成、即时消费的短生命周期数据。 * 每次新的生成会覆盖前一次的建议。 *
* 增加 {@code pending} 映射,避免同一 chatId 的并发请求重复触发 LLM 生成。
*/
@Component
@Slf4j
public class SuggestionCache {
/** 最大缓存条目数,防止无限增长 */
private static final int MAX_ENTRIES = 1000;
/** 生成中任务的并发控制:key=chatId,value=正在执行的生成任务 */
private final ConcurrentHashMap> get(String chatId) {
if (chatId == null) {
return Optional.empty();
}
List
> putIfAbsent(String chatId, CompletableFuture
> future) {
if (chatId == null || future == null) {
return future;
}
CompletableFuture
> existing = pending.putIfAbsent(chatId, future);
if (existing != null) {
return existing;
}
// future 完成后写入缓存并从 pending 移除
future.whenComplete((result, ex) -> {
pending.remove(chatId, future);
if (ex != null) {
log.warn("SuggestionCache 生成任务异常: chatId={}", chatId, ex);
} else if (result != null && !result.isEmpty()) {
put(chatId, result);
}
});
return future;
}
/**
* 清除指定会话的建议缓存(会话删除时调用)。
*
* @param chatId 会话 ID
*/
public void evict(String chatId) {
if (chatId != null) {
cache.remove(chatId);
// 同时取消并清理可能正在进行的生成任务
CompletableFuture
> future = pending.remove(chatId);
if (future != null && !future.isDone()) {
future.cancel(true);
}
log.debug("SuggestionCache 清除: chatId={}", chatId);
}
}
}