Files
DevFlow/src-tauri/src/commands/ai/agentic/guard.rs
绝尘 96a05638b1 重构: 拆agentic.rs第一批GeneratingGuard(strategy自底向上)
- 新建 agentic/guard.rs(69行): GeneratingGuard struct+new/reset/disarm/Drop(F-09 batch2 per_conv双写语义保留, pub(super)可见性)
- agentic.rs 1221→agentic/mod.rs 1165行: mod guard + use GeneratingGuard + 删原定义
- loop主体(run_agentic_loop/try_continue/stream_one_provider/compress)原位保留(后续批,高风险)
helpers未建: 无独立纯helper可抽(DEFAULT_*被state.rs引用留原位, PROTECT_COUNT loop绑定)
主代兜底: cargo check --workspace 0 + test 98 + grep guard抽离/mod.rs use印证
strategy: 自底向上, 单批1-2文件原子, loop主体留后续批(行为敏感需充分测试)
2026-06-19 03:37:28 +08:00

70 lines
2.8 KiB
Rust

//! B-260615-09: generating 状态 RAII guard —— 从 agentic.rs 抽离(重构第一批,纯结构搬迁)。
//!
//! 行为零变更:仅文件位置移动,逻辑/字段/语义完全保留。
//! 调用方(agentic.rs run_agentic_loop)经 `use super::guard::GeneratingGuard;` 复用。
use std::sync::Arc;
use tokio::sync::Mutex;
use crate::commands::ai::AiSession;
/// generating 复位 RAII guard,取代散布的手动 `session.generating = false`。
///
/// 两路复位:
/// - 正常路径:exit 点显式 `reset().await` 即时复位(emit 前调,保证"复位→emit"顺序,
/// 前端收事件时后端已可接下一条)。
/// - 异常路径(panic/未走正常 return):Drop 兜底 spawn 复位,防 generating 永真卡死前端。
///
/// 注:try_continue_agent_loop 不用 guard——其 should_continue=false 路径需保持
/// generating=true(审批等待态),全函数 guard 会误复位;该函数单点 provider-Err 复位保持手动。
///
/// F-260616-09 B 批2:guard 持 `conv_id`,复位改写 `session.conv(&conv_id).generating = false`
/// (per-conv 真相源)。同时**双写顶层 `session.generating = false`** 作共存期桥接 —— 批2
/// 仅迁移 agentic.rs 路径,IPC(ai_is_generating/ai_chat_send)仍读顶层,故 guard 须双写
/// 保证 IPC 读到正确值(否则前端 ai_is_generating 永远 true 卡死发送)。批4 IPC 迁移后
/// 顶层双写移除。
pub(super) struct GeneratingGuard {
session: Arc<Mutex<AiSession>>,
/// guard 所属会话(loop 启动时快照的 conv_id,来自 run_agentic_loop 入参)。
conv_id: String,
done: bool,
}
impl GeneratingGuard {
pub(super) fn new(session: Arc<Mutex<AiSession>>, conv_id: String) -> Self {
Self { session, conv_id, done: false }
}
/// 显式复位 generating=false。emit 前调用保证顺序。幂等。
///
/// 双写:per_conv.conv_id.generating(新真相源)+ 顶层 generating(共存期 IPC 桥接)。
pub(super) async fn reset(&mut self) {
if !self.done {
let mut session = self.session.lock().await;
session.conv(&self.conv_id).generating = false;
self.done = true;
}
}
/// 解除 Drop 兜底复位但不复位 generating。审批等待 return 路径调用:
/// 保持 generating=true 留 try_continue 续生成,同时 Drop 因 done=true 跳过复位 spawn。
/// (B-260615-26: 修复审批执行后对话不续生成回归)
pub(super) fn disarm(&mut self) {
self.done = true;
}
}
impl Drop for GeneratingGuard {
fn drop(&mut self) {
if !self.done {
let session = self.session.clone();
let conv_id = self.conv_id.clone();
tauri::async_runtime::spawn(async move {
let mut s = session.lock().await;
s.conv(&conv_id).generating = false;
});
}
}
}