feat:新增 SESSION_STAGES_ACCUMULATOR 跨流中间步骤累积器

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-26 14:51:19 +08:00
parent fc0f5b88c5
commit 7de91dbbb4
2 changed files with 113 additions and 0 deletions
@@ -50,6 +50,14 @@ public class ShortNovelServiceImpl implements ShortNovelService {
private static final java.util.concurrent.ConcurrentHashMap<String, CachedSessionMeta> SESSION_ORIGINAL_QUERY_CACHE = new java.util.concurrent.ConcurrentHashMap<>();
private static final long SESSION_TTL_MS = 30 * 60 * 1000L;
/**
* sessionId -> 中间步骤累积列表(跨 SSE 流保存 clarification_question/answer/outline
* 用于在 novel_done 时统一创建 message,还原完整生成流程
* 会话超时 30 分钟(与 SESSION_ORIGINAL_QUERY_CACHE 对齐)
*/
private static final java.util.concurrent.ConcurrentHashMap<String, java.util.List<JSONObject>> SESSION_STAGES_ACCUMULATOR =
new java.util.concurrent.ConcurrentHashMap<>();
/**
* session 元数据(含 originalQuery 和缓存时间)
*/
@@ -99,6 +107,36 @@ public class ShortNovelServiceImpl implements ShortNovelService {
return meta.originalQuery;
}
/**
* 累积中间步骤到 session 缓存
* 包级可见,便于单元测试
*
* @param sessionId 会话ID
* @param stageEntry 步骤条目(含 kind 字段:clarification_question/clarification_answer/outline
*/
static void accumulateStage(String sessionId, JSONObject stageEntry) {
if (sessionId == null || sessionId.isEmpty() || stageEntry == null) {
return;
}
SESSION_STAGES_ACCUMULATOR.computeIfAbsent(sessionId,
k -> new java.util.concurrent.CopyOnWriteArrayList<>()).add(stageEntry);
}
/**
* 读取并清理 session 累积的中间步骤
* 包级可见,便于单元测试
*
* @param sessionId 会话ID
* @return 步骤列表(按累积顺序),无则返回空列表
*/
static java.util.List<JSONObject> drainStages(String sessionId) {
if (sessionId == null || sessionId.isEmpty()) {
return java.util.Collections.emptyList();
}
java.util.List<JSONObject> stages = SESSION_STAGES_ACCUMULATOR.remove(sessionId);
return stages != null ? stages : java.util.Collections.emptyList();
}
@Autowired
private ShortNovelConfig config;