Files
UHD_Media_Tool/docs/runbook/dev.md
T
rootandClaude Opus 5.5 3792868816 build(docker): static ffprobe, --allow-run=ffprobe,sha256sum, three supervised processes
entrypoint runs api + worker (io) + worker:agent; compose/runbooks document
WORKER_CONCURRENCY, WORKER_AGENT_CONCURRENCY, ORGANIZE_WALK_MAX_FILES.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 22:15:43 +08:00

98 lines
6.6 KiB
Markdown

# 开发环境运行手册
## 前置
- Deno 2.9.7(锁定;`curl -fsSL https://deno.land/install.sh | sh -s v2.9.7`)、Docker。不需要 Node.js / pnpm。
- 端口:web 5180、API 4380、PG 55433。本机 3000/5175/5176/55432 已被其他项目占用,不要改用。
## 首次启动
```sh
cp .env.example .env # 按需修改;server 与 db 脚本都读仓库根 .env
deno task db:up # 起 postgres:16-alpine(docker-compose.dev.yml,数据卷 umt-pg-data)
deno install # 按 deno.lock 装依赖到 node_modules(成员包软链到 node_modules/@umt/*)
deno task db:migrate # 执行 packages/db/migrations 下全部迁移
deno task dev # 同时起 server(4380)与 web(5180)
```
单独起:`deno task dev:server`(`deno run --watch`,默认 `--role all`,API + worker 同进程)、`deno task dev:web`。
## 验证
```sh
curl localhost:4380/api/v1/health
# 开发模式可用 .env 的 DEV_ADMIN_KEY 作 admin
curl -N -H "Authorization: Bearer umt-dev-admin-key" "localhost:4380/api/v1/events?after=0" # SSE 流(控制台用)
curl -H "Authorization: Bearer umt-dev-admin-key" "localhost:4380/api/v1/events?after=0&limit=50" # JSON 补读页(API Key 调用者用)
```
- OpenAPI:http://localhost:4380/api/openapi.json,文档页 http://localhost:4380/api/docs
- 控制台:http://localhost:5180,右上角钥匙按钮设置 API Key(存 localStorage `umt-api-key`)
## 常用命令
| 命令 | 作用 |
|---|---|
| `deno task ci` | typecheck(tsc 7.0.2 + deno check)→ lint(biome)→ test(vitest)→ check:tokens → build,提交前必须全绿 |
| `deno task typecheck` | `deno types` 生成 `types/deno.d.ts` 后,逐个成员跑 tsc 7.0.2,再跑 `deno check`(Deno 内置 TS 6.0.3) |
| `deno task lint` / `deno task fmt` | biome 检查 / 自动修复(含 import 排序;相对 import 必须带扩展名) |
| `deno task test` | 逐个成员跑 vitest(`deno run -A npm:vitest run`);单包:`cd packages/<x> && deno task test` |
| `deno task db:reset` | 清空 public schema 并重新迁移(生产环境拒绝执行) |
| `deno task gen:types` | 从已迁移的库反射生成 `packages/db/src/types.ts` |
| `deno task gen:tokens` | 改了 app.css 后重新生成 token 登记表 |
| `deno task build` | web 构建到 `apps/web/build/client` + server 编译为单文件 `dist/umt-server` |
| `cd apps/server && deno task start` | 以受限权限(net/env/sys/read)直接跑源码 |
依赖:npm 包版本只在根 `deno.json` 的 `imports` 里登记(web 的前端依赖仍在 `apps/web/package.json`)。改完跑 `deno install` 更新 `deno.lock`。有安装脚本的新依赖需要 `deno approve-scripts` 显式批准。
## 进程角色
`umt-server --role api|worker|worker:agent|all`(源码:`deno run ... apps/server/src/main.ts --role ...`)。
| 角色 | 引擎 worker | OutboxRelay / 模块后台循环 |
|---|---|---|
| `api` | 不起(只入队/信号/取消) | 不跑 |
| `worker`(io 组) | 除 `runAgent`/`resolveDecision` 外的全部任务,并发 `WORKER_CONCURRENCY`(缺省 4) | 跑 |
| `worker:agent` | 只跑 `runAgent`/`resolveDecision`,并发 `WORKER_AGENT_CONCURRENCY`(缺省 2) | 不跑 |
| `all` | io 组 + agent 组两个池(开发缺省) | 跑 |
分组 worker 只认领自己的任务(`@umt/tasks` 按任务名过滤认领),Agent 长会话不占文件复制的槽,反之亦然。
worker 里有事件循环延迟探针:偏差超过 5s 打 `worker 事件循环延迟超过阈值` warn,次数随心跳事件(`loopLagWarnings`)发出。
启动时 `bootstrap()` 装配 `apps/server/src/modules/` 下的四个业务模块(见 apps/server/README.md),并连接任务引擎。数据库不可达时进程启动失败并退出。
acquisition-organize 的后台循环只做编排:qB 同步(含阈值暂停/恢复)一个定时器;另一个定时器按阈值入队 `cleanupDownloadCache`、
巡检补投 `submitDownload`/`verifyAndImport`、每 6h 入队 `reconcileLibrary`,重活都在任务里跑。
`POST /download-cache/cleanup`、`POST /library/reconcile` 同样只入队,返回 `{taskId, runId}`(202)。
HTTP 调用外部 IO 型能力(`release.search` 实时搜索、`release.inspect` 刷新详情、`identity.resolve`、`catalog.lookup` includeRemote)
限时 15s,站点并发 2、TMDB 并发 4,超时 502 / 排队满 429。
一次性子命令(容器入口用):`--role migrate`(迁移到最新,迁移文件已编进二进制;随后迁移任务引擎的 openworkflow schema)、`--role preflight`(启动自检:生产环境拒绝占位符密钥与 root、DB 可达、`WEB_ROOT/index.html` 存在)、`--role probe`(打本机 `/api/v1/health`,HEALTHCHECK 用)。
设置 `WEB_ROOT` 后 API 进程在同一端口托管 web 构建产物:存在的文件直接返回,其余非 `/api` 路径回退 `index.html`。
## Docker 单容器部署
```sh
export SECRET_MASTER_KEY=$(openssl rand -hex 32) POSTGRES_PASSWORD=$(openssl rand -hex 16)
docker compose up -d --build # 服务:app(4380)+ postgres(数据卷 umt-pg-data)
curl localhost:4380/api/v1/health
```
- 镜像:`denoland/deno:2.9.7` 构建 web 与 `deno compile` 出二进制,运行时 `debian:trixie-slim` + gosu + postgresql-client + 静态 ffprobe,root 启动修 `/data` 属主后降权到 PUID(缺省 10001)。
- 入口 `docker/entrypoint.sh`:迁移 → 自检 → 同时起 api、worker、worker:agent 三个进程;任一退出则停掉其余并以非 0 退出,由 `restart: unless-stopped` 拉起。
- 二进制编译时固定权限:`--allow-net --allow-env --allow-sys --allow-read --allow-write --allow-run=ffprobe,sha256sum`;镜像带静态 ffprobe;运行期写入落在 `DATA_DIR`(容器内 `/data`)。完整部署说明见 [deploy.md](deploy.md)。
- 构建版本号:`APP_VERSION=v0.1.0 docker compose build`(写入 web 的 `version.json`)。
## 测试数据库
需要 PG 的测试(db、tasks)默认连 `DATABASE_URL` 或 55433 开发库,不可达时跳过。tasks 包可用 `TASKS_TEST_DATABASE_URL` 指定独立库;每个测试文件使用带 pid+随机后缀的独立 schema,结束时删除,多份测试并发跑也不冲突。
## 排障
- `配置无效`:按提示检查 `.env`,`SECRET_MASTER_KEY` 至少 16 字符,`DATABASE_URL` 必须是 postgres://。
- health 返回 `db: "down"`:`docker compose -f docker-compose.dev.yml ps` 看容器健康状态。
- `deno check` 报找不到 `Deno`:检查根目录是否误放了 `tsconfig.json`(tsc 基座在 `config/tsconfig.base.json`)。
- tsc 报 `Deno` 未定义:先跑 `deno task types` 生成 `types/deno.d.ts`(已 gitignore)。
- 日志中的 passkey/token/cookie/authorization/password 字段与 URL query 参数会被替换为 `[REDACTED]`(含 `logger.child()` 绑定字段与 `err` 的 message/stack);若发现明文,属于缺陷。