添加qiming-rcoder模块
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
# 会话缓存机制
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs)
|
||||
- [model.rs](file://crates/agent_runner/src/model.rs)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件系统性阐述 session_cache 模块如何管理 AI 代理会话状态,涵盖缓存数据结构设计、生命周期管理策略、并发访问控制机制、缓存项的创建/更新/清理流程,以及与代理服务的交互模式。文档还记录内存使用特征、过期策略与性能优化措施,并提供聊天交互与进度查询的实际使用场景示例。
|
||||
|
||||
## 项目结构
|
||||
围绕会话缓存的关键文件组织如下:
|
||||
- 会话缓存核心:session_cache.rs
|
||||
- SSE 进度通知:agent_session_notification.rs
|
||||
- 聊天入口与会话清理:chat_handler.rs
|
||||
- 清理任务与资源回收:cleanup_task.rs
|
||||
- 统一消息模型与通知:agent_session_notify.rs、model.rs
|
||||
- 代理侧会话通知转发:proxy_agent/mod.rs
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "会话缓存层"
|
||||
SC["SessionData<br/>环形缓冲区+命令通道"]
|
||||
PC["PROJECT_SESSION_MAP<br/>项目-会话映射"]
|
||||
GC["全局缓存 SESSION_CACHE<br/>按session_id索引"]
|
||||
end
|
||||
subgraph "代理侧"
|
||||
AC["AcpAgentClient<br/>session_notification回调"]
|
||||
PRJ["PROJECT_AND_AGENT_INFO_MAP<br/>项目-代理状态"]
|
||||
end
|
||||
subgraph "HTTP处理层"
|
||||
SSE["SSE 进度接口<br/>agent_session_notification.rs"]
|
||||
CHAT["聊天接口<br/>chat_handler.rs"]
|
||||
end
|
||||
subgraph "清理与回收"
|
||||
CLEAN["清理任务<br/>cleanup_task.rs"]
|
||||
end
|
||||
AC --> |"推送通知"| SC
|
||||
SSE --> |"建立SSE并创建SessionData"| GC
|
||||
CHAT --> |"清理旧会话/新会话"| GC
|
||||
CLEAN --> |"定期扫描并清理"| GC
|
||||
CLEAN --> |"清理映射"| PC
|
||||
AC --> |"回填request_id上下文"| AC
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L258)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L258)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
|
||||
## 核心组件
|
||||
- 全局会话缓存 SESSION_CACHE:以 session_id 为键,存储每个会话的 SessionData。
|
||||
- 项目-会话映射 PROJECT_SESSION_MAP:确保同一项目仅有一个活跃会话,变更时自动清理旧会话。
|
||||
- SessionData:封装环形缓冲区、命令通道、当前发送器与取消令牌,负责消息入队、实时推送与连接关闭。
|
||||
- SessionWorker:后台工作者,消费命令通道,维护环形缓冲区,按需实时推送消息。
|
||||
- 统一会话消息 UnifiedSessionMessage 与通知 SessionNotify:标准化消息格式,便于跨组件传递。
|
||||
- SSE 进度接口 agent_session_notification:为前端建立 SSE 连接,实时推送会话状态。
|
||||
- 清理任务 cleanup_task:定期扫描并清理闲置代理与孤立会话。
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L1-L120)
|
||||
|
||||
## 架构总览
|
||||
会话缓存的整体交互链路如下:
|
||||
- 代理侧 AcpAgentClient 在收到 session_notification 后,构造 SessionNotify 并调用 push_session_update,统一转为 UnifiedSessionMessage 写入 SessionData。
|
||||
- SSE 进度接口 agent_session_notification 为每个 session_id 创建新的 SessionData 并插入 SESSION_CACHE,随后创建连接并持续推送消息。
|
||||
- 聊天接口 chat_handler 在发起新请求前,会清理旧会话,确保全新开始。
|
||||
- 清理任务定期扫描 PROJECT_SESSION_MAP 与 SESSION_CACHE,清理孤立会话与闲置代理。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Agent as "代理(AcpAgentClient)"
|
||||
participant Cache as "SessionData/Worker"
|
||||
participant SSE as "SSE接口"
|
||||
participant Front as "前端"
|
||||
Agent->>Cache : "push_session_update(SessionNotify)"
|
||||
Cache->>Cache : "SessionWorker : Push消息到环形缓冲区"
|
||||
Cache->>Cache : "尝试实时推送至当前发送器"
|
||||
SSE->>Cache : "create_new_connection(新建SessionData)"
|
||||
Cache-->>SSE : "返回接收端+取消令牌"
|
||||
loop "SSE循环"
|
||||
Cache-->>SSE : "推送UnifiedSessionMessage"
|
||||
SSE-->>Front : "SSE事件"
|
||||
end
|
||||
Note over SSE,Cache : "取消令牌触发或发送端关闭时,SSE断开"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 会话缓存数据结构与生命周期
|
||||
- 数据结构设计
|
||||
- SESSION_CACHE:全局 DashMap,键为 session_id,值为 Arc<SessionData>,保证并发安全与零拷贝共享。
|
||||
- SessionData:包含命令发送端、当前发送器与取消令牌的互斥保护,避免竞态。
|
||||
- SessionWorker:持有环形缓冲区(HeapRb),按最大容量维护消息队列,实时推送失败时自动清理当前发送器。
|
||||
- PROJECT_SESSION_MAP:全局 DashMap,键为 project_id,值为 session_id,确保同一项目仅有一个活跃会话。
|
||||
- 生命周期管理
|
||||
- 新建:SSE 接口为每个 session_id 创建新的 SessionData 并插入 SESSION_CACHE,覆盖旧值,确保“全新开始”。
|
||||
- 销毁:SessionWorker 退出时,SessionData 仍驻留缓存;清理任务通过移除映射与缓存条目实现资源回收。
|
||||
- 连接关闭:主动触发 CancellationToken 或显式关闭发送端,使接收端 recv() 返回 None,SSE 自然断开。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class SessionData {
|
||||
+command_tx
|
||||
+current_sender
|
||||
+current_cancel
|
||||
+new(max_size)
|
||||
+create_new_connection(buffer_size)
|
||||
+push_message(message)
|
||||
+close_current_connection()
|
||||
+message_count()
|
||||
}
|
||||
class SessionWorker {
|
||||
-max_size
|
||||
-command_rx
|
||||
-current_sender
|
||||
-current_cancel
|
||||
+spawn(...)
|
||||
+run()
|
||||
}
|
||||
class UnifiedSessionMessage {
|
||||
+session_id
|
||||
+message_type
|
||||
+sub_type
|
||||
+data
|
||||
+timestamp
|
||||
+heartbeat(session_id)
|
||||
}
|
||||
class SessionNotify {
|
||||
+to_unified_message()
|
||||
}
|
||||
SessionData --> SessionWorker : "spawn并消费命令"
|
||||
SessionWorker --> UnifiedSessionMessage : "生产消息"
|
||||
SessionNotify --> UnifiedSessionMessage : "转换"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L24-L221)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
|
||||
|
||||
### 并发访问控制机制
|
||||
- 全局缓存与映射
|
||||
- 使用 LazyLock 初始化 DashMap,保证线程安全与延迟初始化。
|
||||
- SessionData 内部对 current_sender/current_cancel 使用 Mutex 包裹,避免多处同时写入导致的竞争。
|
||||
- 命令通道
|
||||
- SessionData 内部使用无界 mpsc 通道接收命令,SessionWorker 异步消费,避免阻塞代理通知路径。
|
||||
- 取消令牌
|
||||
- 每次创建新连接都会生成新的 CancellationToken,旧连接一旦被新连接抢占或用户取消,立即触发取消,确保旧连接快速失效。
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
|
||||
### 缓存项创建、更新与清理流程
|
||||
- 创建
|
||||
- SSE 接口为 session_id 创建 SessionData 并插入 SESSION_CACHE,同时创建连接并返回接收端与取消令牌。
|
||||
- 更新
|
||||
- 代理侧 session_notification 回调将 SessionUpdate 转为 SessionNotify,再转为 UnifiedSessionMessage,通过 SessionData.push_message 入队。
|
||||
- SessionWorker 将消息写入环形缓冲区,并尝试实时推送至当前发送器;若推送失败则清空当前发送器,避免脏写。
|
||||
- 清理
|
||||
- SSE 接口:当取消令牌被触发或发送端关闭时,SSE 断开,旧 SessionData 仍保留,等待清理任务回收。
|
||||
- 清理任务:扫描 PROJECT_SESSION_MAP 与 SESSION_CACHE,移除孤立会话与空闲代理,减少内存占用。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> Create["SSE接口创建SessionData并插入缓存"]
|
||||
Create --> Push["代理推送SessionNotify->UnifiedSessionMessage"]
|
||||
Push --> Buffer["SessionWorker写入环形缓冲区"]
|
||||
Buffer --> Realtime{"实时推送成功?"}
|
||||
Realtime --> |是| SSELoop["SSE循环推送消息"]
|
||||
Realtime --> |否| ClearSender["清空当前发送器"]
|
||||
SSELoop --> Cancel{"取消令牌触发/发送端关闭?"}
|
||||
Cancel --> |是| Close["SSE断开,旧SessionData保留"]
|
||||
Cancel --> |否| Heartbeat["周期心跳"]
|
||||
Close --> Cleanup["清理任务扫描并移除"]
|
||||
Cleanup --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
章节来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
### 与代理服务的交互模式
|
||||
- 代理侧 AcpAgentClient 实现 session_notification 回调,将 ACP SessionUpdate 转为 AgentSessionUpdate,再包装为 SessionNotify,最终调用 push_session_update 写入缓存。
|
||||
- 若 SessionNotification.meta 中未携带 request_id,则通过 PROJECT_AND_AGENT_INFO_MAP 查找 project_id,再从 SESSION_REQUEST_CONTEXT 获取 request_id,确保消息携带 request_id 以便前端关联。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ACP as "ACP客户端"
|
||||
participant Client as "AcpAgentClient"
|
||||
participant Cache as "push_session_update"
|
||||
participant Worker as "SessionWorker"
|
||||
participant SSE as "SSE接口"
|
||||
ACP->>Client : "session_notification(SessionUpdate)"
|
||||
Client->>Client : "提取/回填request_id"
|
||||
Client->>Cache : "SessionNotify -> UnifiedSessionMessage"
|
||||
Cache->>Worker : "命令 : Push"
|
||||
Worker->>Worker : "写入环形缓冲区"
|
||||
Worker->>SSE : "尝试实时推送"
|
||||
SSE-->>Client : "SSE循环接收并转发"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L231-L257)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
|
||||
章节来源
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L231-L257)
|
||||
|
||||
### 过期策略与内存使用特征
|
||||
- 过期策略
|
||||
- 心跳消息:SSE 接口在建立连接后立即发送心跳,并按周期发送心跳事件,用于维持连接活性。
|
||||
- 取消与断开:取消令牌触发或发送端关闭时,SSE 断开;SessionWorker 退出后,SessionData 仍驻留缓存,等待清理任务回收。
|
||||
- 孤立会话清理:清理任务扫描 SESSION_CACHE 中不在活跃映射中的 session_id,若消息计数大于 0 则移除条目,否则标记为空会话清理。
|
||||
- 内存使用特征
|
||||
- 环形缓冲区:按最大容量维护最近消息,满时淘汰最旧消息,避免无限增长。
|
||||
- 连接级缓存:每次 SSE 连接都会创建新的 SessionData,覆盖旧值,确保不会累积历史消息。
|
||||
- 映射表:PROJECT_SESSION_MAP 仅保存活跃映射,清理任务移除无效映射,降低内存压力。
|
||||
|
||||
章节来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L385-L475)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L173-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
### 性能优化措施
|
||||
- 极简设计
|
||||
- SessionData 直接共享当前发送器与取消令牌,避免命令传递带来的额外开销。
|
||||
- SessionWorker 直接从共享状态获取发送器,实时推送失败时立即清空,避免后续无效尝试。
|
||||
- 通道与锁粒度
|
||||
- 使用无界命令通道与细粒度 Mutex,降低锁竞争概率。
|
||||
- 心跳与断开
|
||||
- 心跳事件降低连接空闲时的网络压力;取消令牌与发送端关闭确保旧连接快速失效,避免资源浪费。
|
||||
- 清理策略
|
||||
- 定期清理孤立会话与闲置代理,减少缓存与映射膨胀。
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L241)
|
||||
|
||||
## 依赖关系分析
|
||||
- 组件耦合
|
||||
- session_cache 与 agent_session_notification:SSE 接口依赖 SessionData 的创建与连接能力。
|
||||
- proxy_agent/mod 与 session_cache:代理侧通知通过 push_session_update 写入缓存,二者通过统一消息模型解耦。
|
||||
- chat_handler 与 session_cache:聊天接口在发起新请求前清理旧会话,确保全新开始。
|
||||
- cleanup_task 与 session_cache/PROJECT_SESSION_MAP:清理孤立会话与映射,避免资源泄漏。
|
||||
- 外部依赖
|
||||
- DashMap 提供并发安全的哈希表。
|
||||
- ringbuf HeapRb 提供高效环形缓冲区。
|
||||
- tokio mpsc 提供异步通道与取消令牌。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["agent_session_notification.rs"] --> B["session_cache.rs"]
|
||||
C["proxy_agent/mod.rs"] --> B
|
||||
D["chat_handler.rs"] --> B
|
||||
E["cleanup_task.rs"] --> B
|
||||
E --> F["PROJECT_SESSION_MAP"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L258)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
章节来源
|
||||
- [model.rs](file://crates/agent_runner/src/model.rs#L1-L12)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
|
||||
|
||||
## 性能考量
|
||||
- 环形缓冲区容量:根据业务负载调整最大容量,平衡内存占用与消息保留范围。
|
||||
- 实时推送失败处理:推送失败时清空发送器,避免后续无效尝试;必要时增加接收端缓冲大小。
|
||||
- 心跳频率:合理的心跳间隔可在保持连接活性与网络开销之间取得平衡。
|
||||
- 清理周期:清理任务的间隔与闲置超时可根据系统负载动态调整,避免过于频繁或过少。
|
||||
|
||||
## 故障排查指南
|
||||
- SSE 连接无法建立
|
||||
- 检查 SSE 接口是否成功创建 SessionData 并插入 SESSION_CACHE。
|
||||
- 确认 create_new_connection 是否返回接收端与取消令牌。
|
||||
- 实时消息未到达前端
|
||||
- 检查 SessionWorker 是否成功写入环形缓冲区与尝试实时推送。
|
||||
- 若推送失败,确认当前发送器是否被清空,以及取消令牌是否被触发。
|
||||
- 旧会话消息残留
|
||||
- 确认 SSE 接口是否为每个 session_id 创建新的 SessionData 并覆盖旧值。
|
||||
- 检查清理任务是否正确扫描并移除孤立会话。
|
||||
- 代理通知未写入缓存
|
||||
- 确认 AcpAgentClient 的 session_notification 回调是否正确提取 request_id 并调用 push_session_update。
|
||||
- 检查 SessionData 是否存在且未被清理。
|
||||
|
||||
章节来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L241)
|
||||
|
||||
## 结论
|
||||
session_cache 模块通过 SessionData + SessionWorker + 环形缓冲区的组合,实现了高并发、低开销的会话状态缓存与实时推送。配合 SSE 进度接口、聊天入口清理策略与定期清理任务,系统在保证消息实时性的同时,有效控制内存与资源占用,满足 AI 代理会话状态管理的需求。
|
||||
|
||||
## 附录
|
||||
|
||||
### 实际使用场景示例
|
||||
- 聊天交互
|
||||
- 前端调用聊天接口,后端为项目生成或复用会话,清理旧会话后启动代理任务,SSE 接口实时推送执行进度。
|
||||
- 进度查询
|
||||
- 前端通过 /agent/progress/{session_id} 建立 SSE 连接,接收 prompt_start、agent_message_chunk、tool_call 等事件,结合心跳维持连接活性。
|
||||
|
||||
章节来源
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
Reference in New Issue
Block a user