# Runtime Runbook **Date:** 2026-02-25 **Status:** Active **Audience:** 运维 / 后端值班 ## Scope & Preconditions 本手册用于日常值班、发布前检查、故障处置与回滚。 ### 前置条件 - 已配置 `.env`(仓库根目录)。 - 主机可用:`docker`、`docker compose`、`tmux`、`uv`。 - 已拉取最新代码并确认当前分支与目标发布版本一致。 ### 红线规则 - 禁止跳过 bootstrap gate 直接启动 web/worker。 - 迁移/初始化容器执行时必须带 `--build`,避免旧镜像导致迁移不生效。 --- ## Bootstrap Gate (Mandatory) 以下流程必须按顺序执行。 ### Step 1: 启动基础设施 ```bash docker compose --env-file .env -f infra/docker/docker-compose.yml up -d ``` 通过标准:`docker compose ... ps` 中 redis/supabase 相关容器为 `running`。 ### Step 2: 执行迁移与初始化 #### 生产环境 ```bash docker compose --env-file .env -f infra/docker/docker-compose.yml run --rm --build init-job uv run python -m core.runtime.cli bootstrap ``` #### 开发环境(推荐) 开发阶段推荐使用脚本,直接使用本地代码,无需构建镜像: ```bash bash infra/scripts/dev-migrate.sh bootstrap ``` 可选命令: - `bash infra/scripts/dev-migrate.sh migrate` - 仅运行迁移 - `bash infra/scripts/dev-migrate.sh init-data` - 仅初始化数据 通过标准:命令退出码为 0,日志中无 migration/init-data 错误。 ### Step 3: 版本核对(建议) ```bash docker compose --env-file .env -f infra/docker/docker-compose.yml exec -T db \ psql -U postgres -d postgres -c "SELECT version_num FROM public.alembic_version;" ``` 通过标准:返回 1 行版本号,且与发布预期版本一致。 --- ## Service Start / Stop (tmux) ### 启动应用进程 ```bash bash infra/scripts/app.sh start ``` 该脚本会在 tmux `social-dev` 会话中拉起: - web - worker-critical - worker-default - worker-bulk 通过标准:`tmux list-windows -t social-dev` 可见上述窗口。 ### 常用 tmux 命令 ```bash tmux list-windows -t social-dev tmux attach -t social-dev tmux kill-session -t social-dev ``` ### 日志文件 | 服务 | 日志文件 | |------|---------| | Web | `logs/web.log`, `logs/errors/web.error.log` | | Worker Critical | `logs/worker-critical.log`, `logs/errors/worker-critical.error.log` | | Worker Default | `logs/worker-default.log`, `logs/errors/worker-default.error.log` | | Worker Bulk | `logs/worker-bulk.log`, `logs/errors/worker-bulk.error.log` | --- ## Operational Verification 按优先级分层执行。 ### L1 必跑(发布前/故障恢复后必须) ```bash # 先导入 .env,确保端口与配置一致 set -a . ./.env set +a WEB_BASE_URL="http://127.0.0.1:${SOCIAL_WEB__PORT:-5775}" # 基础健康 curl -fsS http://127.0.0.1:${SOCIAL_SUPABASE__KONG_HTTP_PORT:-8000}/health # compose 状态 docker compose --env-file .env -f infra/docker/docker-compose.yml ps # 核心接口 smoke curl -sS -X POST "${WEB_BASE_URL}/api/v1/auth/login" \ -H 'Content-Type: application/json' \ -d '{"email":"demo@example.com","password":"secret123"}' ``` 通过标准:health 返回 2xx,关键容器 `running`,核心接口返回预期业务状态码。 ### L2 可选(Auth/Profile 业务回归) ```bash # signup start curl -sS -X POST "${WEB_BASE_URL}/api/v1/auth/verifications" \ -H 'Content-Type: application/json' \ -d '{"username":"demo","email":"demo@example.com","password":"secret123"}' # signup verify curl -sS -X POST "${WEB_BASE_URL}/api/v1/auth/verifications/verify" \ -H 'Content-Type: application/json' \ -d '{"email":"demo@example.com","token":"123456"}' # signup resend curl -sS -X POST "${WEB_BASE_URL}/api/v1/auth/verifications/resend" \ -H 'Content-Type: application/json' \ -d '{"email":"demo@example.com"}' # profile patch curl -sS -X PATCH "${WEB_BASE_URL}/api/v1/profile/me" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer " \ -d '{"username":"demo2","bio":"hello"}' # profile get curl -sS "${WEB_BASE_URL}/api/v1/profile/me" \ -H "Authorization: Bearer " ``` 通过标准:接口返回符合预期的 2xx 或受控业务错误,无 5xx。 ## Incident Playbook ### 1) 迁移未生效(常见于旧镜像) - 症状:字段/表结构与代码不一致,接口报 schema 错误。 - 定位:检查 `alembic_version` 与容器镜像构建时间。 - 修复:重新执行 `init-job --build`,并复核版本号。 ### 2) Worker 不消费任务 - 症状:队列堆积,任务长时间 pending。 - 定位:检查 `worker-*` tmux 窗口和对应日志文件。 - 修复:重启 tmux 会话,确认并发配置与队列名(critical/default/bulk)。 - 说明:Taskiq 路径当前仅消费 `SOCIAL_WORKER__GROUPS__*__CONCURRENCY`,旧 Celery 参数(prefetch/time_limit 等)已废弃。 ### 2.1) Agent Runtime run/resume 事件不闭环 - 症状:`POST /api/v1/agent/runs` 返回 202,但前端事件流没有 `RUN_FINISHED`。 - 定位步骤: ```bash # 1) 检查 taskiq worker 是否消费 agent 任务 grep -E "tasks\.agent\.run_command|RUN_STARTED|RUN_FINISHED|RUN_ERROR" logs/worker-default.log # 2) 检查 API SSE 事件读取(带 Last-Event-ID) curl -N "${WEB_BASE_URL}/api/v1/agent/runs//events" \ -H "Authorization: Bearer " \ -H "Last-Event-ID: 1-0" # 3) 检查 Redis 连通(必要时) docker compose --env-file .env -f infra/docker/docker-compose.yml exec -T redis redis-cli ping ``` - 修复建议: - 若 worker 无消费:重启 `worker-default` 窗口并确认 `core.agent.infrastructure.queue.tasks` 已被 Taskiq worker 加载。 - 若 worker 有事件但 API 无输出:排查 Redis stream 前缀配置与 session_id 是否一致。 - 若出现 `RUN_ERROR`:按 error_id 回查后端日志,不在 API/SSE 中暴露敏感上下文。 ### 3) JWT 或认证异常 - 症状:接口持续 401/403。 - 定位:核对 `.env` 中 Supabase JWT 配置与签发方设置。 - 修复:修正配置后重启 web 进程并执行 L1/L2 验证。 ### 4) Auth 邮件模板未生效 / 注册返回超时但邮件已发送 - 症状: - 收到默认英文模板(非 `infra/mail-templates`)。 - `signup/start` 偶发 500 或超时,但邮箱仍收到验证码邮件。 - 根因:容器配置漂移(旧容器未按最新 compose/.env 重建),导致: - `supabase-auth` 缺少 `GOTRUE_MAILER_TEMPLATES_*` 环境变量。 - `supabase-mail-templates` 仍挂载旧路径。 - 定位: ```bash docker inspect supabase-auth --format '{{ range .Config.Env }}{{ println . }}{{ end }}' | grep GOTRUE_MAILER_TEMPLATES docker inspect supabase-mail-templates --format '{{ range .Mounts }}{{ .Source }} -> {{ .Destination }}{{ println }}{{ end }}' ``` - 修复:强制重建 auth 和 mail-templates(不改其他服务): ```bash docker compose --env-file .env -f infra/docker/docker-compose.yml up -d --force-recreate --no-deps mail-templates auth ``` - 复核标准: - `docker inspect supabase-auth` 能看到 `GOTRUE_MAILER_TEMPLATES_CONFIRMATION/RECOVERY`。 - `supabase-mail-templates` 挂载源为 `infra/mail-templates`。 - `POST /api/v1/auth/verifications` 返回 `202` 且耗时恢复正常。 --- ## Rollback Procedure ### 回滚前检查 - 确认目标回滚提交或版本号。 - 确认是否涉及不可逆数据变更。 ### 回滚执行 1. 停止应用进程:`tmux kill-session -t social-dev` 2. 切换代码到目标版本。 3. 按目标版本要求执行迁移回滚(如有)。 4. 重新执行 bootstrap gate 与 service 启动。 ### 回滚后复核 - 执行 L1 必跑检查。 - 记录回滚原因、时间、影响范围和后续修复计划。 --- ## Change Log | 日期 | 变更 | |------|------| | 2026-02-24 | 创建运行时手册,删除 legacy 脚本,统一使用 gunicorn | | 2026-02-24 | 清理配置:合并 AppSettings 到 WebSettings,删除 Worker 旧配置 (enabled_queues/queues),统一使用 SOCIAL_WEB__GUNICORN__* 命名 | | 2026-02-24 | 开发阶段 compose 暂不编排 web/worker,仅保留 redis/supabase 与 init-job | | 2026-02-24 | 新增 dev-app-up 脚本:手动基础设施后,一键 bootstrap + tmux 拉起 web/worker | | 2026-02-25 | 补充迁移防遗漏规则:容器迁移命令统一追加 --build;开发调试优先使用本地 CLI 一次性迁移脚本 | | 2026-02-25 | Auth 注册切换为 OTP 三段式:signup/start、signup/verify、signup/resend;邮件模板改为纯验证码展示 | | 2026-02-25 | 清理未使用配置类:删除 WebSettings/GunicornSettings/WorkerSettings/WorkerGroupSettings(脚本仍使用环境变量启动服务) | | 2026-03-04 | Agent 运行时进入硬切重构:移除旧 Agent Chat 验证章节,待新方案落地后补充 | | 2026-02-25 | 简化启动方式:dev-app-up -> app-up,分离 bootstrap 与服务启动 | | 2026-02-25 | 重构为运维分层手册:Bootstrap Gate、分层验证、故障与回滚流程 | | 2026-02-25 | 新增配置漂移故障条目:修复 Auth 邮件模板失效与 signup 超时场景 | | 2026-02-27 | 用户搜索支持邮箱精确匹配:query 含 @ 符号时走 auth.users → profiles 两步查询 | | 2026-02-28 | 邀请码功能:新增 invite_codes 表、profiles.referred_by,注册时可选填邀请码并记录邀请关系 | | 2026-03-02 | 文档整理:修正 auth 端点名称(/verifications)、补充 profile 路由文档、修复 L2/L3 验证命令 | | 2026-03-02 | 修正 bootstrap 命令:init-job 需要使用 `uv run python -m core.runtime.cli bootstrap` | | 2026-03-05 | 新增 Agent Runtime run/resume/events 运维排障流程(Taskiq + Redis + Last-Event-ID) |