脚本 exec 立即返回 running 并在后台跑批次;/ws/alerts 推送 script_progress/complete; 新增 ScriptRunsPage、Telegram 汇总通知与可配置的浏览器完成提示音。 Co-authored-by: Cursor <cursoragent@cursor.com>
6.1 KiB
设计说明 — 脚本库全局执行进度 + Telegram 结果通知
日期: 2026-06-08
基线: main@3f995a7
参考 UI: VSnackbarQueue Promise · VProgressLinear chunks · VAlert 可关闭
背景与目标
运维在脚本库对 300+ 台执行命令时,需要:
- 点击执行后立即返回,不阻塞对话框/页面,可在其他页面继续操作。
- 全局顶部展示执行进度(流动状进度条 +「已进行 3 台,剩余 363 台」)。
- 执行结束时:浏览器提醒 + 短促提示音;可点击关闭,1 秒渐隐。
- Telegram 推送汇总:成功 N / 失败 M;失败项含服务器名称、退出码、原因摘要(可多条)。
现状差距
| 能力 | 现状 | 缺口 |
|---|---|---|
| 后台执行 | POST /api/scripts/exec 同步 await 全部批次(366 台可阻塞数十秒~数分钟) |
须改为「创建 execution → 立即返回 → 后台 dispatch」 |
| 进度 UI | ScriptsPage 底部「批量执行状态」+ 10s 轮询 | 须全局 Snackbar Queue + 细粒度进度 |
| 实时推送 | Push 有 /ws/sync;脚本无 WS |
须新增 script_progress 广播或复用 alerts WS |
| Telegram | 仅有 send_telegram_sync_complete |
须新增 send_telegram_script_complete + 设置项 |
| 完成提醒 | 终态仅 snackbar(warning) |
须 Alert + 声音 + 渐隐动画 |
方案对比
A. 后台执行 + WebSocket 进度(推荐)
POST /exec → 202 + execution_id
↓
asyncio.create_task(run_batches)
↓ 每完成一台/一批
broadcast_script_progress → /ws/alerts 或 /ws/scripts
↓ 终态
send_telegram_script_complete + WS terminal event
优点:进度实时、与 Push 模式一致、Snackbar 可流畅更新。
缺点:需改后端执行模型 + WS 协议。
B. 仅前端全局轮询
API 仍同步,或改为后台但前端 2s 轮询 GET /executions/{id}。
优点:改动小。
缺点:366 台时 API 仍可能长时间不返回;轮询粗、流量大;不符合「先返回再执行」。
选定 A。
接口与数据模型
API 变更
| 端点 | 变更 |
|---|---|
POST /api/scripts/exec |
创建 execution + init_live 后立即返回 { id, status: "running", progress: "0/N" };dispatch 在 asyncio.create_task |
POST /api/scripts/executions/{id}/retry |
同上异步模式 |
GET /api/scripts/executions/{id} |
不变(轮询兜底) |
兼容:长任务(long_task)逻辑保持;短任务也走同一异步路径。
WebSocket 消息(扩展 /ws/alerts 或新建 /ws/scripts)
推荐 扩展 /ws/alerts(App 已连接),新增 type:
{
"type": "script_progress",
"execution_id": 6,
"label": "磁盘检查",
"status": "running",
"done": 3,
"success": 3,
"failed": 0,
"total": 366,
"remaining": 363
}
终态:
{
"type": "script_complete",
"execution_id": 6,
"status": "partial",
"success": 363,
"failed": 3,
"total": 366,
"failed_preview": [
{ "server_id": 1, "name": "srv-a", "exit_code": 1, "summary": "Connection timed out" }
]
}
done = 已有终态结果的台数(含失败);success 沿用 execution_progress_summary 语义(失败不计入 success)。
Telegram
新增 send_telegram_script_complete(),参照 send_telegram_sync_complete:
- 设置项:
NOTIFY_SCRIPT_COMPLETE(默认true,Settings 可关) - 正文:脚本名/命令摘要、操作人、成功/失败/总计、耗时
- 失败明细:每台一行 —
名称 · exit码 · 原因摘要(HTML escape + sanitize) - 超过 Telegram 4096 字符:首批 20 条 +「…及其他 N 台,详见 Nexus #/scripts 执行 #id」
- 触发点:
script_execution_store.apply_update(..., terminal=True)或 dedicatedon_execution_terminalhook
前端全局 UI
| 组件 | 用途 |
|---|---|
VSnackbarQueue |
全局顶部(location="top"),每任务一条 queue item |
VProgressLinear buffer-value + indeterminate 交替 |
「流动状」进度;model-value = done/total*100 |
VAlert closable + @click:close + CSS transition 1s |
完成提醒条(成功/部分失败/全失败配色) |
Audio / new Audio('/app/notify.mp3') |
终态播放一次(用户可浏览器静音) |
Snackbar 文案示例(进行中):
磁盘检查 · 已进行 3 台,剩余 363 台
Promise 模式:queue 项在 script_complete 时 resolve,切换为 Alert 或关闭 snackbar 并弹出 Alert。
状态管理:新建 useScriptExecutionQueue(Pinia 或 composable singleton),ScriptsPage / SchedulesPage 提交后只调用 queue.track(executionId, label, total),移除页面内 trackedExecs 面板(或保留「详情」链接)。
安全与性能
- WS 消息仅 JWT 已连接管理员可见;不含完整 stderr(Telegram 同样截断)。
- 后台 task 须捕获异常写 execution
failed,避免 silent hang。 - 366 台 Telegram 分条/截断,防 flood。
- 单 worker:
create_task绑定 primary worker 约定(与现有 background tasks 一致)。
验收标准
- 选 366 台点执行 → 1s 内关闭对话框,顶部出现进度 Snackbar。
- 切换至 Dashboard/其他页,进度条仍更新。
- 文案显示「已进行 X 台,剩余 Y 台」,X+Y=总数(进行中);Y 随完成递减。
- 全部结束:短促提示音 + 顶部 Alert「成功 363 台,失败 3 台」;点击后 1s 渐隐。
- Telegram 收到汇总 + 3 台失败名称与原因。
- Settings 关闭
NOTIFY_SCRIPT_COMPLETE时不发 Telegram。 - 长任务 / retry / 临时命令 行为一致。
非目标(本期不做)
- 多 execution 合并为一条 Telegram(每台 execution 一条)。
- 浏览器 Push Notification API(仅站内 Alert + 声音)。
- 修改
success/total进度语义。