容错处理

This commit is contained in:
董宏凯 committed 2026-05-20 12:51:04 +08:00
1 parent f44e2ccf52
commit f358cfb7c7
8 files changed
+988 -21

No files matched your search

@@ -1,3 +1,86 @@
/**
* AI 写作入口页(左右双栏:聊天面板 + 草稿预览)。
*
* ──────────────────────────────────────────────────────────────────────────
* Docker 内网部署后「会话丢失 / transcript 报 500 / resume 报 400」排查指南
* ──────────────────────────────────────────────────────────────────────────
*
* 后端涉及接口(前缀 /api/ai-writing):
* POST /start 启动写作流程
* GET /{session_id}/stream SSE 进度流
* POST /{session_id}/resume 提交用户干预 → 继续流程
* PUT /sessions/{session_id}/transcript 保存对话时间线
*
* ── 1) 确认 alembic 迁移已跑过(修 transcript 500)─────────────────────
* transcript 列在 MySQL 上原是 TEXT(64 KB 上限),长时间线会溢出抛 500。
* 迁移 20260519_02 把它改成 LONGTEXT。容器启动会自动跑,验证方法:
*
* docker exec <gateway> sh -c "cd /app/backend \
* && PYTHONPATH=. uv run alembic current"
* docker exec <mysql> mysql -uroot -p<pwd> deerflow -e \
* "SHOW COLUMNS FROM ai_writing_sessions LIKE 'transcript';"
*
* 列类型应是 longtext。若仍是 text,手动执行:
* docker exec <gateway> sh -c "cd /app/backend \
* && PYTHONPATH=. uv run alembic upgrade head"
*
* ── 2) 确认 .deer-flow 数据卷已挂出(修「容器没重启也丢会话」)──────
* AI 写作 graph 的 checkpointer 已从 MemorySaver 换成 AsyncSqliteSaver,
* 文件落到 .deer-flow/data/checkpoints.db。docker-compose 必须把该目录
* 挂出来,否则容器重启数据照样丢:
*
* services:
* gateway:
* volumes:
* - ./data:/app/.deer-flow # 关键:挂出 .deer-flow
*
* ── 3) 确认 worker 数 = 1(关键嫌疑:多 worker 内存隔离)────────────
* _event_queues / _session_pending_pause 都是模块级 dict,每个 worker
* 一份。多 worker 下,/start 命中 worker A、/resume 命中 worker B,B
* 的 dict 没有这个 session → 404/「会话丢失」。
*
* docker exec <gateway> ps -ef | grep -E 'uvicorn|gunicorn'
*
* 若 > 1:要么把启动参数改成 --workers 1,要么在 nginx 加 sticky
* session(ip_hash / cookie),要么把队列搬 Redis。
*
* ── 4) 排查节点异常(嫌疑:graph 节点抛错触发清理分支)─────────────
* _stream_graph_segment 的 except 分支会清掉 _event_queues[session_id],
* 用户下一次 resume 就 404。日志里搜:
*
* docker logs <gateway> 2>&1 | grep -E \
* 'ai_writing graph segment failed|ai_writing.*error' | tail -50
*
* ── 5) 排查反向代理掐 SSE 长连接(嫌疑:proxy_read_timeout 太短)───
* SSE 默认连接挂半个小时以上,nginx 默认 60s 会断。检查内网反代:
*
* grep -rE 'proxy_read_timeout|sse|keepalive' /etc/nginx/
*
* 需在 SSE 路由上加:proxy_read_timeout 3600s; proxy_buffering off;
*
* ── 定期清理(每天 03:00 跑)────────────────────────────────────────
* config.yaml -> ai_writing.cleanup 段(retention_days: 7)。联动清理
* MySQL 业务表 + SQLite checkpointer 里的 thread 状态。手动验证:
*
* docker exec <mysql> mysql -uroot -p<pwd> deerflow -e \
* "SELECT COUNT(*) FROM ai_writing_sessions \
* WHERE updated_at < NOW() - INTERVAL 7 DAY;"
*
* ── 不想等凌晨 3 点?手动触发一次清理(admin only)──────────────────
* POST /api/ai-writing/admin/cleanup
* Body(全部可选,留空走 config 默认):
* { "retention_days": 7, "only_finished": false, "batch_size": 500 }
* 返回:
* { "deleted_db": N, "deleted_checkpoints": N,
* "elapsed_seconds": X, "params": {...} }
*
* 例:清掉所有 1 小时前的会话(测试用):
* curl -X POST http://<gateway>/api/ai-writing/admin/cleanup \
* -H 'Content-Type: application/json' \
* -H 'Cookie: <admin session cookie>' \
* -d '{"retention_days": 0}'
* ──────────────────────────────────────────────────────────────────────────
*/
import { useRef } from 'react';
import { TooltipProvider } from '@/components/ui/tooltip';
import type { GroupImperativeHandle } from 'react-resizable-panels';