fix: use rust healthcheck for code queue mgr

This commit is contained in:
Codex
2026-05-19 17:15:55 +00:00
parent 541a93604d
commit 22a0b709f2
4 changed files with 31 additions and 3 deletions
+1 -1
View File
@@ -111,7 +111,7 @@ services:
volumes:
- ${UNIDESK_LOG_DIR}:/var/log/unidesk
healthcheck:
test: ["CMD", "bun", "-e", "fetch('http://127.0.0.1:4278/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
test: ["CMD", "code-queue-mgr", "--healthcheck"]
interval: 5s
timeout: 3s
retries: 20
+2 -2
View File
@@ -12,7 +12,7 @@ Production runtime and CI/CD control-plane versioning follow `docs/reference/rel
- `dev-frontend-proxy` 是主 server 上的 18083 dev UI 薄入口,代理到 D601 `unidesk-dev/frontend-dev`,详细边界见 `docs/reference/dev-environment.md`
- `provider-gateway` 是当前主 server 的本机计算节点代理,通过 WebSocket 主动连到 provider ingress,挂载 `/var/run/docker.sock` 作为自动任务执行主路径,使用 `pid: "host"` 读取节点级进程资源,并周期性上报系统资源指标、进程占用与 Docker daemon 状态;计算节点 provider-gateway 还必须把 egress proxy 仅发布到宿主 loopback `127.0.0.1:18789` 供本节点执行环境出网,维护用 Host SSH / WSL SSH 私钥目录只读挂载到 `/run/host-ssh`,不得作为自动任务调度主路径。
- `todo-note` 是主 server 承载的 Todo Note 纯后端用户服务,容器名 `todo-note-backend`,只在 Compose 内网暴露 `4211/tcp`,使用主 PostgreSQL 存储迁移后的 Todo Note 数据。
- `code-queue-mgr` 是主 server 承载的轻量 Code Queue 控制面用户服务,容器名 `code-queue-mgr-backend`,只在 Compose 内网暴露 `4278/tcp`,只连接主 PostgreSQL,负责 `code-queue` 稳定代理路径下的队列管理、任务提交、历史摘要、已读状态和轻量 Trace 读取;不得引入 Codex/OpenCode/Playwright/Chromium/Docker socket/runner 依赖。
- `code-queue-mgr` 是主 server 承载的轻量 Code Queue 控制面用户服务,容器名 `code-queue-mgr-backend`,只在 Compose 内网暴露 `4278/tcp`,只连接主 PostgreSQL,负责 `code-queue` 稳定代理路径下的队列管理、任务提交、历史摘要、已读状态和轻量 Trace 读取;不得引入 Codex/OpenCode/Playwright/Chromium/Docker socket/runner 依赖。生产镜像是 Rust slim runtimeCompose healthcheck 必须调用镜像内 `code-queue-mgr --healthcheck` 或等价 Rust 探针,不得依赖 Bun runtime。
- `k3sctl-adapter` 是 D601 上由 UniDesk 直管的 k3s 控制面适配微服务,容器名 `k3sctl-adapter`,只绑定 `127.0.0.1:4266`,由 UniDesk frontend/backend-core 通过用户服务代理访问并提供 `/api/control-plane` 可见性。
- `code-queue` 是稳定对外用户服务 ID。backend-core 对 `/api/microservices/code-queue/proxy/...` 做内部职责分流:控制/读取路径默认转到主 server `code-queue-mgr`D601 k3s `code-queue-read`/`code-queue-write`/`code-queue-scheduler` 只承担执行面兼容、scheduler/runner、dev-container、judge 和 running task control。D601 执行面通过 `src/components/microservices/k3sctl-adapter/k3s/code-queue.k3s.json` 声明,运行对象通过 `code-queue.k8s.yaml` 创建 Kubernetes Deployment/ClusterIP Service;任务、queue、未读状态、控制状态和通知 outbox 一律写入主 PostgreSQL,不保留本地状态文件 fallback。
- `project-manager` 是主 server 承载的项目管理用户服务,容器名 `project-manager-backend`,仅在 Compose 内网暴露 `4233/tcp`,项目清单写入主 PostgreSQL,浏览器只能通过 UniDesk frontend 同源代理执行增删改查、Excel 导入和 Excel 导出。
@@ -52,7 +52,7 @@ frontend 改动必须明确上线到公网:修改 `src/components/frontend/src
frontend 的 artifact 上线顺序为:先运行必要的轻量本地校验或 D601 CI;然后发布 `127.0.0.1:5000/unidesk/frontend:<commit>`;再用 dev/prod `deploy apply` 消费该 artifact;最后验证 dev `frontend-dev` 和 prod `frontend``/health.deploy.commit`、image label、`UNIDESK_DEPLOY_*` metadata 都等于 requested commit。若必须手工复现维护路径,等价 Docker Compose 命令只能是固定 project/env 的 `docker compose --env-file .state/docker-compose.env -f docker-compose.yml -p unidesk build frontend`,随后 `docker compose --env-file .state/docker-compose.env -f docker-compose.yml -p unidesk up -d --no-deps --force-recreate frontend`;手工路径仍必须做同样的健康检查,不得改用全栈 `up --build``down`、删除容器或重启 database/backend-core 来“顺手上线”前端。
单服务重建必须由 CLI 解析出的 Compose 命令执行,且只能影响目标 service,不得连带重启 database、backend-core 或其他未指定服务。重建后 job 必须按 Docker Compose label 校验目标容器:`com.docker.compose.project` 等于 `config.json` 中的固定 project name`com.docker.compose.service` 等于目标服务名,并等待容器进入 `healthy`;没有 healthcheck 的服务至少要进入 `running`。如果验证失败,job 必须失败并输出目标容器状态,禁止把“无输出”或“只完成 build”当作成功。
单服务重建必须由 CLI 解析出的 Compose 命令执行,且只能影响目标 service,不得连带重启 database、backend-core 或其他未指定服务。重建后 job 必须按 Docker Compose label 校验目标容器:`com.docker.compose.project` 等于 `config.json` 中的固定 project name`com.docker.compose.service` 等于目标服务名,并等待容器进入 `healthy`;没有 healthcheck 的服务至少要进入 `running`。如果验证失败,job 必须失败并输出目标容器状态,禁止把“无输出”或“只完成 build”当作成功。`code-queue-mgr` 的 post-up validation 依赖 Docker health 状态,因此其 healthcheck 必须在 Rust runtime 镜像内自洽可执行,不能引用不存在的 `bun`
紧急灾备或数据迁移期间如需手工启动单个 Compose service,也必须保持与 CLI 相同的隔离语义:使用固定 `--env-file .state/docker-compose.env``up -d --no-deps <service>`,只启动目标容器;如果需要刷新 backend-core 的服务目录或环境变量,应把 `backend-core` 作为显式目标单独重建/替换,不能依赖 `up` 的依赖解析顺手重建 database、backend-core 或其他服务。
+1
View File
@@ -85,6 +85,7 @@ OA Event Flow 在 UniDesk 语境中按共享控制面基础设施管理:不得
- 职责:队列 CRUD、任务提交、批量提交、任务移动、queued prompt edit、已读状态、历史摘要、overview、stats、summary、prompt、output/transcript/trace 的轻量 PostgreSQL 读取。
- 非职责:不运行 Codex/OpenCode,不包含 Playwright/Chromium,不持有 Docker socket,不创建 dev-container,不执行 judge,不管理 active run steer/interrupt,不做任务调度或 runner。
- 资源边界:目标常驻内存不超过 100 MB,默认 PostgreSQL pool 为 `CODE_QUEUE_MGR_DATABASE_POOL_MAX=2``CODE_QUEUE_TRACE_DATABASE_POOL_MAX=1``/health` 必须暴露 `role=master-control-plane``schemaReady`、连接池上限和 `noRunnerDependencies=true`
- Runtime healthcheck:生产镜像是 Rust slim runtime,不包含 BunDocker Compose healthcheck 必须使用镜像内 `code-queue-mgr --healthcheck``127.0.0.1:4278/health` 做带超时探针,或使用等价的 Rust binary 子命令。不得把 TypeScript/Bun `fetch` 探针用于 `code-queue-mgr`,否则 `server rebuild code-queue-mgr` 的 post-up validation 会误判失败。
- 路由:CLI/WebUI 仍只访问 `/api/microservices/code-queue/proxy/...`backend-core 在内部把控制/读取路径转到 `code-queue-mgr`,把 active run、judge、dev-container、执行面健康和 scheduler 相关路径转到 D601 执行面。
- 行为兼容:提交与 queued prompt edit 必须保留 Code Queue 环境提示注入、`--reference-task-id`/引用输入解析和引用任务上下文注入,避免 master 控制面路径与 D601 原写服务语义分叉。
+27
View File
@@ -189,6 +189,32 @@ function unifiedLogRotationItem(): CheckItem {
};
}
function codeQueueMgrHealthcheckItem(): CheckItem {
const composeText = readFileSync(rootPath("docker-compose.yml"), "utf8");
const serviceStart = composeText.indexOf("\n code-queue-mgr:");
const nextService = serviceStart >= 0 ? composeText.indexOf("\n todo-note:", serviceStart + 1) : -1;
const serviceBlock = serviceStart >= 0
? composeText.slice(serviceStart, nextService >= 0 ? nextService : undefined)
: "";
const dockerfileText = readFileSync(rootPath("src/components/microservices/code-queue-mgr/Dockerfile"), "utf8");
const sourceText = readFileSync(rootPath("src/components/microservices/code-queue-mgr/src-rs/main.rs"), "utf8");
const healthcheckUsesRustProbe = serviceBlock.includes("code-queue-mgr") && serviceBlock.includes("--healthcheck");
const healthcheckReferencesBun = /\bhealthcheck:[\s\S]*?\bbun\b/u.test(serviceBlock);
const binaryCopiedIntoRuntime = dockerfileText.includes("/usr/local/bin/code-queue-mgr");
const binaryImplementsProbe = sourceText.includes("--healthcheck") && sourceText.includes("run_healthcheck");
return {
name: "docker-compose:code-queue-mgr-rust-healthcheck",
ok: healthcheckUsesRustProbe && !healthcheckReferencesBun && binaryCopiedIntoRuntime && binaryImplementsProbe,
detail: {
healthcheckUsesRustProbe,
healthcheckReferencesBun,
binaryCopiedIntoRuntime,
binaryImplementsProbe,
expected: "code-queue-mgr Rust runtime healthcheck must use code-queue-mgr --healthcheck and must not depend on bun/curl/wget being present.",
},
};
}
function rustCheckItem(): CheckItem {
if (process.env.UNIDESK_D601_RUST_CHECK !== "1") {
return {
@@ -216,6 +242,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
{ name: "config:validated", ok: true, detail: { project: config.project.name, runtime: config.runtime } },
commandItem("bun:version", ["bun", "--version"]),
syntaxItem(),
codeQueueMgrHealthcheckItem(),
];
if (options.files) {
items.push(