Files
UHD_Media_Tool/docs/plan/03-decoupling-audit.md
T
2026-09-27 22:15:51 +08:00

30 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 主线程解耦审计(2026-09-27,只读审计结论 → W4-D 修复清单)
## 结论
生产容器 API 与 worker 分进程;RSS/快照/刮削/入库主链路走任务引擎 + outbox。漏网三类:
1. HTTP 请求内同步重活:`POST /library/reconcile`(全量 stat)、`POST /download-cache/cleanup`(删种删数据)、`POST /organization`(planImport 递归 walk)、`POST /capabilities/{id}/invoke` 中 release.search/release.inspect/identity.resolve/catalog.lookup(远程站点/TMDB)、`GET /inventory/media-servers`(串行 Emby)。
2. acquisition-organize 后台循环(index.ts)绕过引擎直接调 `submitDownload`、`executeRecord`(Copy/Move)、`cleanupDownloadCache`、`reconcileLibrary`,串行 await;无租约/attemptToken 保护;一次大复制卡住 qB 同步与阈值暂停。
3. worker 并发度固定 4(openworkflow-engine.ts),runAgent 整段会话占 1 槽数分钟,与 verifyAndImport 大文件复制抢同一池。
事件循环丢租约风险低(复制/哈希流式让出;租约 30s/续租 15s);强制 sha256 路径(目标已存在、跨设备恢复)会全量读两遍。
## 修复清单(W4-D)
- P0 后台循环只编排:sweepPendingImports → enqueue verifyAndImport;sweepReservedPlans → enqueue submitDownload;超阈值清理与 6h 对账 → enqueue(幂等键按时间槽);tick 只剩 syncDownloads + 阈值判断,qB 同步独立定时器。
- P0 `/download-cache/cleanup`、`/library/reconcile` 改入队返回 {taskId, runId}(enqueueTracked);前端经任务页/SSE 追踪。
- P1 `WORKER_CONCURRENCY` 配置;worker 分组:`--role worker`(io 组:除 runAgent/resolveDecision 外,并发 4)与 `worker:agent`(并发 1–2),`startWorker` 两次各带 versions;模块 start() 循环只在 io 组;entrypoint 起三进程。
- P1 capabilities invoke 分级:外部 IO 型能力在 HTTP 路径强制 `AbortSignal.timeout(15s)` + 按站点/TMDB 限并发,或改入队返回 taskId;`POST /organization` dryRun 的 walk 加文件数上限。
- P2 fs/copy.ts:highWaterMark 1MiB;强制 sha256 全量比对改子进程 `sha256sum`(仿 ffprobe.ts 的 Deno.Command);executeRecord 打点。
- P2 worker 事件循环延迟探针(setInterval 偏差 >5s warn)。
## W4-D 修复状态(2026-09-27)
| 项 | 状态 | 说明 |
|---|---|---|
| P0 后台循环只编排 | 已完成(fe9693d) | `acquisition-organize/index.ts` 拆成两个自调度定时器:`sync`(syncDownloads + 阈值暂停/恢复)与 `plan`(编排)。超阈值 → 入队 `cleanupDownloadCache`(业务键 `threshold:<5min 槽>`,上一轮 pending/running 时跳过);`sweepReservedPlans` → 入队 `submitDownload`(业务行 `plan:<id>`,引擎键 `…:<5min 槽>`,上次 run 仍活跃则跳过);`sweepPendingImports` → 入队 `verifyAndImport`(业务行 `import:<dtId>`,同上);6h 对账 → 入队 `reconcileLibrary`(`auto:<6h 槽>`)。顺带修正:补入库巡检改按 `completed_at` 选(同步每轮刷新 `updated_at`,原条件永远选不中)。测试 `__tests__/background-loop.test.ts`:巡检只入队、50MB 入库(复制 + sha256 + 2.5s 慢 ffprobe)进行中 mock qB `torrents/info` 请求间隔 < 1s |
| P0 cleanup / reconcile 端点入队 | 已完成(fe9693d) | `POST /download-cache/cleanup`、`POST /library/reconcile` 改 `enqueueTracked` 返回 `{taskId, runId}`(202,幂等键按分钟槽);前端"立即清理"提示任务 id 并跳 `/console/engine/<runId>` |
| P1 worker 分组 + 并发配置 | 已完成(a9cee69、473c5e9、3792868) | `WORKER_CONCURRENCY`(4)/`WORKER_AGENT_CONCURRENCY`(2);`--role worker`(io 组 + relay + 模块循环)、`--role worker:agent`(runAgent/resolveDecision)、`--role all`(两池同进程);`@umt/tasks` 带 versions 的 worker 在认领 SQL 上按任务名过滤(OpenWorkflow 原生认领不看任务名,误认领会按 5s→5m 退避)。entrypoint 三进程互相看护。测试 `packages/tasks/test/worker-groups.test.ts`(去掉过滤即失败) |
| P1 capabilities invoke 分级 | 已完成(473c5e9) | `modules/agent/invoke-limits.ts`:release.search(实时搜索)/release.inspect(refreshDetail)/identity.resolve/catalog.lookup(includeRemote)在 HTTP 路径 15s 超时(502)+ 站点并发 2 / TMDB 并发 4(排队超时 429);许可在底层调用真正结束后才归还 |
| P1 `POST /organization-records` walk 上限 | 已完成(f9c20c6) | `ORGANIZE_WALK_MAX_FILES`(5000);dryRun 超出返回 `truncated: true`(计划只含前 N 个),正式执行 `too_many_files` 失败 |
| P2 copy highWaterMark / sha256 子进程 / 打点 | 已完成(f9c20c6) | 读写流 1 MiB;强制全量 sha256(复制后回读、目标已存在比对、跨卷恢复、计划期同尺寸目标)走 `Deno.Command("sha256sum")`,不可用(未安装 / 无 --allow-run)回退进程内流式,结果记 `hashVia`,`sha256Stats()` 计数;executeRecord 每文件打 `organize.transfer` 日志(耗时/字节/MB/s/hashVia) |
| P2 worker 事件循环延迟探针 | 已完成(473c5e9) | 1s 采样,偏差 > 5s warn + 计数,随心跳事件发 `loopLagWarnings/maxLoopLagMs` |
| 打包遗留 | 已完成(f6457a2、3792868) | 镜像带静态 ffprobe(mwader/static-ffmpeg:7.1.1),编译 `--allow-run=ffprobe,sha256sum`;`settings.agent.sessionDir`(null = DATA_DIR/agent-sessions)进设置页;镜像压缩 107→160.5 MB(ffprobe 层 135 MB 未压缩);umtw4d 临时部署验证 health、三进程、ffprobe/sha256sum 可调用 |
| 未做 | 遗留 | `GET /inventory/media-servers` 串行 Emby 仍在请求内(审计列出但不在 W4-D 清单);invoke 超时后底层调用继续跑完(handler 不全认 signal) |