Files
Nexus/docs/design/plans/2026-06-08-script-exec-global-progress-telegram.md
T
2026-07-08 22:31:31 +08:00

6.9 KiB
Raw Blame History

实施计划 — 脚本库全局执行进度 + Telegram 通知

日期: 2026-06-08
设计: 2026-06-08-script-exec-global-progress-telegram-design.md

分期概览

阶段 内容 估时 依赖
P0 后端异步 exec + terminal hook 1d
P1 WS script_progress / script_complete 0.5d P0
P2 Telegram send_telegram_script_complete 0.5d P0
P3 前端全局 SnackbarQueue + Progress + Alert + 声音 1d P1
P4 ScriptsPage 接入 / 移除页内面板 0.5d P3
P5 测试、changelog、audit、部署 0.5d P0P4

合计:约 3–4 人日(单 Agent 连续实施)。


P0 — 后端:异步执行(关键路径)

涉及文件

文件 变更
server/application/services/script_service.py execute_command 拆为 start_execution + _run_execution_batches
server/api/scripts.py /exec/retry 立即返回 running
server/main.py 确保 task 异常日志 + 可选 task 注册防 shutdown 丢失

步骤

  1. execute_command 创建 DB/Redis 记录后 asyncio.create_task(_run_execution_batches(...))
  2. 将现有 batch 循环移入 _run_execution_batches,逻辑不变。
  3. Task 顶层 try/except:异常时 apply_update(status=failed, terminal=True)
  4. API 返回 get_execution_detail(id)status=running, progress=0/N)。
  5. 注意:同一 worker 内 task 即可;多 worker 时 Redis live 已是 SSOT(已满足)。

测试

  • tests/test_script_execution_async.pymock dispatch,断言 POST /exec 立即返回 & 后台终态。

P1 — WebSocket 进度广播

涉及文件

文件 变更
server/api/websocket.py broadcast_script_progress / broadcast_script_complete
server/infrastructure/redis/script_execution_store.py apply_update 中调用 broadcast(或 script_service 批次回调)
server/application/services/script_job_callback.py long_task 单台 callback 时也 broadcast

步骤

  1. 定义消息 schema(见 design doc)。
  2. 每批 batch_progress 或每台完成后推送(366 台建议每完成 1 台或每批推送,避免 WS 风暴可 batch 每 5 台)。
  3. 前端 useWebSocket.ts 解析 script_progress / script_complete

P2 — Telegram 脚本执行结果

涉及文件

文件 变更
server/infrastructure/telegram/__init__.py send_telegram_script_complete
server/config.py NOTIFY_SCRIPT_COMPLETE
server/api/settings.py 设置项读写(若 NOTIFY_* 走 settings 表)
terminal hook 组装 failed 列表(server name + exit_code + stderr 首行)

步骤

  1. 复用 send_telegram_sync_complete 结构与 _notify_enabled
  2. 失败明细:查 server repo 取 namesummary 用 sanitize_external_message
  3. 超长分片或截断 + 指向 execution #id。
  4. 单测:mock httpx,断言 HTML 含失败台名。

P3 — 前端全局 UIVuetify 4

涉及文件

文件 变更
frontend/src/App.vue VSnackbarQueue 替换单条 v-snackbar;挂载 ScriptExecProgressHost
新建 frontend/src/components/script/ScriptExecProgressHost.vue Queue item 模板:ProgressLinear chunks + 文案
新建 frontend/src/composables/useScriptExecutionQueue.ts track / onProgress / onComplete / playSound
新建 frontend/src/components/script/ScriptExecCompleteAlert.vue VAlert closable + 1s leave transition
frontend/public/notify.mp3 或 assets 提示音(短、免版权)

UI 行为

  1. 进行中SnackbarQueue 顶部,location="top"timeout="-1"(手动关闭或完成关闭)。
  2. 进度条v-progress-linear rounded height="6" :model-value="done/total*100" :buffer-value="..." 制造流动感(见 Vuetify chunks 示例)。
  3. 完成
    • Snackbar queue 项 resolvePromise API)。
    • 显示 VAlerttype=success/warning/error),closable,点击关闭触发 v-fade-transition 1000ms。
    • new Audio(...).play().catch(() => {})(静默处理自动播放策略拦截)。
  4. Alert 可点「查看详情」→ router.push('#/scripts') + openExecDetail(id)(通过 event bus 或 query)。

与现有 $snackbar 兼容

  • 保留 window.$snackbar 给普通 toast;脚本进度走独立 queue,避免互相覆盖。

P4 — ScriptsPage 接入

涉及文件

文件 变更
frontend/src/pages/ScriptsPage.vue submitExecqueue.track();删除/隐藏页内「批量执行状态」卡片
frontend/src/pages/SchedulesPage.vue 若 schedule 触发 exec,同样 track(可选 P4+

步骤

  1. doRun / doQuickExecPOST 成功后 showRun=false,调用 queue.track(id, label, total)
  2. 移除 trackedExecs / pollTimer / activeTrackedExecs(逻辑迁至 composable)。
  3. WS 断线时 composable 降级 3s 轮询直至终态。

P5 — 验证与交付

pytest tests/test_script_execution_async.py tests/test_telegram_script.py -q
cd frontend && npx vite build
bash scripts/local_verify.sh

手动验收

  1. 生产 10 台脚本:顶部进度 + 完成 Alert + 声音。
  2. 366 台(或 staging):Telegram 汇总与失败明细。
  3. 关闭 Telegram 通知设置后无推送。

文档

  • docs/changelog/2026-06-08-script-exec-global-progress-telegram.md
  • docs/audit/2026-06-08-script-exec-global-progress-telegram.md
  • 更新 AI-HANDOFF-2026-06-08.md

回滚

  • 后端:revert commit;进行中的 execution 靠 Redis live 继续,无 schema 迁移。
  • 前端:revert + vite build deploy。

风险与对策

风险 对策
366 台 WS 消息过多 节流:每批或每 5 台推送一次
浏览器拦截自动播放 首次用户手势后解锁;Alert 仍可见
异步 exec 重复提交 可选:同脚本 running 时 confirmP4+
Telegram 过长 截断 + 链接 execution id
多 Tab 重复声音 localStorage leader election 或仅 focused tab 播放

建议实施顺序(给 Agent

P0 异步 API → P1 WS → P2 Telegram → P3 全局 UI → P4 ScriptsPage 接入 → P5 验证部署

请先确认设计再写代码perfect-implementation 纪律)。