- fix: infinite message loop in workflow orchestrator - feat: restore realtime LLM streaming from report generator to frontend - refactor: major update to provider services (generic workers, workflow adapters) - refactor: common contracts and message definitions updated - feat: enhanced logging and observability in orchestrator - docs: update project management tasks and status - chore: dependency updates and config adjustments
4.0 KiB
4.0 KiB
任务:Realtime Logs 数据流优化 (缓冲与回放) [已完成]
目标
解决前端 Realtime Logs 面板在页面刷新、重新连接或初始加载延迟时丢失日志的问题。
目标是确保 "First-hand" 服务端日志能够可靠地流向前端,不依赖 NATS 的临时性。
实施方案
1. 后端:增强 SyncStateCommand (Orchestrator)
我们需要修改 handle_sync_state 逻辑,使其在发送状态快照的同时,也能读取当前的临时日志文件,并将历史日志作为事件发送给前端。
- 修改
workflow.rs->handle_sync_state:- 调用
log_manager.read_current_logs(req_id)(需要新增此方法,非破坏性读取)。 - 读取到的日志内容可能是巨大的字符串。为了不阻塞 NATS 消息,可以分块发送,或者作为
WorkflowStateSnapshot的一部分发送(如果大小允许)。 - 方案选择: 发送一个新的事件类型
WorkflowLogHistory或者复用TaskLog(批量发送)。 - 鉴于前端
handleEvent处理TaskLog是追加式的,我们可以循环发送TaskLog事件。 - 更优方案: 在
WorkflowStateSnapshot结构体中增加logs: Vec<String>字段。这样前端在恢复快照时一次性填入。
- 调用
2. 定义数据结构变更
common-contracts/src/messages.rs:- 修改
WorkflowStateSnapshot,增加logs: Vec<String>。
- 修改
3. 完善 LogBufferManager
logging.rs:- 新增
read_current_logs(&self, request_id: &str) -> Result<Vec<String>>。 - 读取文件,按行分割,返回
Vec<String>。
- 新增
4. 前端适配
useWorkflowStore.ts:- 在
handleEvent->WorkflowStateSnapshot分支中,处理event.payload.logs。 - 将这些日志合并到
state.logs(Global Logs) 或者解析后分发到state.tasks(如果日志格式包含 Task ID)。 - 目前日志格式为
[ISO Time] [Level] Message,不一定包含 Task ID,所以主要作为 Global Logs 展示。
- 在
5. 流程梳理
- 前端启动/刷新:
- 调用
SSE /events/{id}。 - API Gateway 收到连接,订阅 NATS,并发送
SyncStateCommand给 Orchestrator。
- 调用
- Orchestrator:
- 收到
SyncStateCommand。 - 生成 DAG 快照。
- 读取
temp_logs/{id}.log。 - 构建
WorkflowStateSnapshot(包含 logs)。 - 发布到 NATS。
- 收到
- 前端接收:
- 收到 Snapshot。
- 恢复 DAG 状态。
- 恢复 Logs 面板内容。
- 后续实时日志:
- Orchestrator 继续运行,Tracing Layer 写入文件。
- 关键点: 我们之前删除了
publish_log。现在需要恢复实时推送能力,但不是手动调用。 - 方案:
FileRequestLogLayer除了写文件,还应该有一个机制将日志推送到 NATS 吗? - 回答: 是的。之前的重构把推送删了,导致前端收不到实时更新了。
- 修正:
FileRequestLogLayer应该同时负责:- 写文件 (持久化缓冲)。
- 推送到 NATS (实时展示)。
- 技术难点: Layer 是同步的,NATS 是异步的。
- 解决: 使用
tokio::sync::broadcast或mpsc通道。Layer 将日志发送到通道,有一个后台 Task 负责接收通道消息并推送到 NATS。
修正后的后端任务列表
- 恢复实时推送通道:
- 在
AppState中增加一个log_broadcast_tx(sender)。 FileRequestLogLayer持有这个 sender。- 在
main.rs启动一个后台任务,监听 receiver,将日志封装为WorkflowEvent::TaskLog并推送到 NATS。
- 在
- 实现历史回放 (Snapshot):
- 修改
WorkflowStateSnapshot增加logs字段。 LogBufferManager增加读取方法。handle_sync_state填充 logs。
- 修改
前端任务列表
- 更新
WorkflowStateSnapshot类型定义。 - 在 Store 中处理 Snapshot 携带的日志。
这个方案兼顾了实时性和可靠性(断线重连)。