修复: aichat 切换/新建对话缺陷(队列串会话/回切丢消息/审批误终态化/删除复活/切换链路)
This commit is contained in:
@@ -223,10 +223,8 @@ async fn save_conversation_inner(
|
||||
// 累积致 token 暴增。仅影响持久化视图,不污染内存真相源(ContextManager)——build_for_request
|
||||
// 仍读全量 messages。
|
||||
//
|
||||
// F-260616-09 B 批4:per_conv.messages 唯一真相源(conv_id 来源:本函数入参,与 save 落库的 conv 一致)。
|
||||
// loop 内 save 由 run_agentic_loop 入参 conv_id 透传;IPC 路径(commands.rs)save 也传 conv_id。
|
||||
// conv() 惰性建:save 路径 conv 必然已建(send/regenerate/edit/switch 均先 conv());若极端
|
||||
// 未建(如启动恢复无 live conv),conv() 建空 PerConvState,save 空 messages(幂等不污染)。
|
||||
// per_conv.messages 是唯一真相源(conv_id 来源:本函数入参,与 save 落库的 conv 一致)。
|
||||
// conv() 惰性建:save 路径 conv 必然已建;极端未建(如启动恢复无 live conv)建空态,save 空消息(幂等)。
|
||||
// BUG-2026-07-19: lock 段只 clone 必要读(messages + 元数据),truncate 移出 lock。
|
||||
// 原 clone+truncate 全在 lock 内,对话历史长(多轮+大工具结果)时 clone+truncate 持锁可达秒级,
|
||||
// 致 guard.reset/process_tool_calls 等 session lock 竞争超时(aichat 卡死连环:工具卡片不呈现+
|
||||
@@ -238,6 +236,16 @@ async fn save_conversation_inner(
|
||||
// 避免同时持有 session 的 mut 和 immut 借用(E0502)。
|
||||
let (mut msgs, provider_id, created_at, pinned_goals, persisted_count, needs_full_rewrite) = {
|
||||
let mut session = session_arc.lock().await;
|
||||
// 已删除对话直接跳过写入(loop 在「push 后、save 前」被删除的幽灵复活根治):
|
||||
// 此处不惰性重建 per_conv、不触发 INSERT 空壳 + insert_batch 复活。
|
||||
// 删除语义:删了就删了,后续 save 不应复活。return 前 guard 自动 drop(MutexGuard),无持锁泄漏。
|
||||
if session.deleted_convs.contains(conv_id) {
|
||||
tracing::debug!(
|
||||
"save_conversation 跳过已删除对话(loop 在途 save 不复活): conv_id={}",
|
||||
conv_id
|
||||
);
|
||||
return;
|
||||
}
|
||||
let __wait = __lock_start.elapsed();
|
||||
let provider_id = session.active_provider_id.clone();
|
||||
let created_at = session.active_conv_created_at.clone();
|
||||
@@ -386,6 +394,19 @@ async fn save_conversation_inner(
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
// 兜底二次校验(封在途 save 走到 Ok(None) 的复活窗口):save 起始时可能尚未
|
||||
// 记录删除标记,但 get_by_id 恰在 DB 删除之后返回 Ok(None)——INSERT 前再确认一次。
|
||||
let deleted_now = {
|
||||
let session = session_arc.lock().await;
|
||||
session.deleted_convs.contains(conv_id)
|
||||
};
|
||||
if deleted_now {
|
||||
tracing::debug!(
|
||||
"save_conversation 落库前检测到对话已删除,跳过 INSERT(不复活): conv_id={}",
|
||||
conv_id
|
||||
);
|
||||
return;
|
||||
}
|
||||
// 懒创建首次落库(此为空对话不落库的落库点:走到这里 messages 必非空)
|
||||
// messages JSON 列首次落库也写(兼容未跑迁移的老库 fallback 读路径),
|
||||
// 同时写 ai_messages(新读路径真相源)。
|
||||
|
||||
Reference in New Issue
Block a user