docs: record worker concurrency rollout

This commit is contained in:
Your Name
2026-07-02 12:08:49 +08:00
parent 79d310ba29
commit af5396c127
3 changed files with 153 additions and 21 deletions
+9 -5
View File
@@ -70,7 +70,7 @@ All canary code writes must use `/Users/john/Project/memind_canary/...`.
## All-user Gray Profile
Current production rollout can use all H5 users by leaving the user and task-type allowlists empty. Validation metadata is accepted when present, but not required for the H5 default code-run path.
Current production rollout can use all H5 users by leaving the user and task-type allowlists empty. H5 default code-run now auto-attaches receipt validation, so required validation stays enabled.
Portal `.env` additions:
@@ -79,7 +79,9 @@ MEMIND_AGENT_RUN_AUTODISPATCH=0
MEMIND_AGENT_CODE_RUNS_ENABLED=1
MEMIND_AGENT_CODE_RUNS_USER_IDS=
MEMIND_AGENT_CODE_RUN_TASK_TYPES=
MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=0
MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=1
MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2
MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2
MEMIND_TOOL_GATEWAY_ENABLED=0
MEMIND_TOOL_GATEWAY_DRY_RUN=0
VITE_AGENT_CODE_RUNS_ENABLED=1
@@ -92,8 +94,8 @@ Worker installer environment:
```bash
MEMIND_AGENT_RUN_WORKER_START=1
MEMIND_AGENT_RUN_WORKER_POLL_MS=3000
MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=1
MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=1
MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2
MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2
MEMIND_TOOL_GATEWAY_ENABLED=1
MEMIND_TOOL_GATEWAY_DRY_RUN=0
```
@@ -104,12 +106,14 @@ Expected values:
toolRuntime.codeRunPolicy.enabled=true
toolRuntime.codeRunPolicy.userAllowlist=[]
toolRuntime.codeRunPolicy.taskTypeAllowlist=[]
toolRuntime.codeRunPolicy.requireValidation=false
toolRuntime.codeRunPolicy.requireValidation=true
toolRuntime.codeRunsEnabled=true
toolRuntime.queue.autoDispatch=false
toolRuntime.queue.maxConcurrentRuns=2
toolRuntime.queue.toolGateway.enabled=false
check-agent-run-worker.expected=running
check-agent-run-worker.running=true
check-agent-run-worker.processes includes --limit 2
```
## Enable Procedure
@@ -19,12 +19,12 @@
- Stream Controller 已具备 SSE headers、abort propagation、backpressure pipeline。
- Redis Router 已启用,承担 worker runtime state。
- Goose Worker Pool 已从固定单点走向四 worker 可观测调度。
- Aider/OpenHands 已从普通聊天默认能力中剥离,进入 code mode 和后端灰度门禁;P6.3 已把 code run 从 goosed session extension 外移到 `agent-run-v1` Tool Gateway 协议,P6.4 已完成 Aider 真实执行 canaryP6.5 已完成 OpenHands 真实执行 canaryP6.6 已完成 external worker 精确接管 code-run canaryP6.7 已加入 Tool Gateway 产物校验与输出审计,P6.8 已安装 external worker LaunchAgentP6.9 已完成带 validation 的 external worker 灰度 canaryP6.10 已加入 external worker 只读观测脚本,P6.11 已加入放量策略门禁,P6.12 已开启全用户长期灰度并通过普通测试用户真实路径,P6.13 已安装自动暂停 guardP6.15 已让 H5 code-run 自动补 receipt validation 并恢复后端 required validation。
- Aider/OpenHands 已从普通聊天默认能力中剥离,进入 code mode 和后端灰度门禁;P6.3 已把 code run 从 goosed session extension 外移到 `agent-run-v1` Tool Gateway 协议,P6.4 已完成 Aider 真实执行 canaryP6.5 已完成 OpenHands 真实执行 canaryP6.6 已完成 external worker 精确接管 code-run canaryP6.7 已加入 Tool Gateway 产物校验与输出审计,P6.8 已安装 external worker LaunchAgentP6.9 已完成带 validation 的 external worker 灰度 canaryP6.10 已加入 external worker 只读观测脚本,P6.11 已加入放量策略门禁,P6.12 已开启全用户长期灰度并通过普通测试用户真实路径,P6.13 已安装自动暂停 guardP6.15 已让 H5 code-run 自动补 receipt validation 并恢复后端 required validationP6.17/P6.18 已把 external worker 并发 2 通过 canary 并固化为当前 all-user gray 策略
- PG 和 MindSpace 仍保持生产数据边界,SLO 报告只做统计读取;P6.3-P6.15 不新增 schema migration,不删除或修改既有用户数据。
整体执行评分: 9.95 / 10。
可以支撑当前 H5 streaming 稳定性改造的基础目标。自动采样、worker sidecar heartbeat、SLO 只读快照、SLO 日报定时器、SLO 日报保留策略、first-token EWMA、first-token p50/p95 窗口趋势、Tool Gateway Queue v0、外部 worker 接管入口、真实 worker canary、后端 code-mode canary、code-run 用户级灰度 gate、H5 页面编辑 UI canary、P6.3 Tool Gateway 协议化、P6.4 Aider 真实 canary、P6.5 OpenHands 真实 canary、P6.6 external worker code-run canary、P6.7 Tool Gateway guardrails、P6.8 worker LaunchAgent、P6.9 validated external worker canary、P6.10 worker observability、P6.11 rollout policy gates、P6.12 all-user gray、P6.13 auto-pause guardP6.15 H5 validation metadata 已经落地。主要剩余差距转为更细粒度的任务级产物规范用户可见进度/失败说明,以及后续是否提高 worker 并发
可以支撑当前 H5 streaming 稳定性改造的基础目标。自动采样、worker sidecar heartbeat、SLO 只读快照、SLO 日报定时器、SLO 日报保留策略、first-token EWMA、first-token p50/p95 窗口趋势、Tool Gateway Queue v0、外部 worker 接管入口、真实 worker canary、后端 code-mode canary、code-run 用户级灰度 gate、H5 页面编辑 UI canary、P6.3 Tool Gateway 协议化、P6.4 Aider 真实 canary、P6.5 OpenHands 真实 canary、P6.6 external worker code-run canary、P6.7 Tool Gateway guardrails、P6.8 worker LaunchAgent、P6.9 validated external worker canary、P6.10 worker observability、P6.11 rollout policy gates、P6.12 all-user gray、P6.13 auto-pause guardP6.15 H5 validation metadata 和 P6.17/P6.18 worker concurrency 2 已经落地。主要剩余差距转为 running/stuck recovery、DB/session auth 瞬时错误收敛、更细粒度的任务级产物规范用户可见进度/失败说明。
## 实测结果
@@ -866,20 +866,54 @@ Data boundary:
- event chain 包含 `tool_gateway_validation`
- SLO `ok=true``failures=[]`guard `shouldPause=false`
### P6.17 / P6.18 Worker Concurrency 2
结果: 通过,两条真实 code-run 并发执行成功,并发 2 已成为当前 all-user gray 生产策略。
- worker LaunchAgent:
- `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2`
- `MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2`
- args include `--limit 2`
- `KeepAlive=true`
- Portal runtime/status:
- `toolRuntime.queue.maxConcurrentRuns=2`
- canary:
- run `d064c8c0-b061-4df7-8c9b-5dfa315271ea`
- run `64717bcc-4065-4947-a0d3-a706f3b62640`
- both `succeeded`, attempts `1`
- both include `tool_gateway_validation`
- started timestamps differ by `51ms`, proving concurrent dispatch.
- post-check:
- worker running
- queue empty
- guard `shouldPause=false`
- SLO `ok=true`, `failures=[]`
- observation:
- Portal had one restart-window `read EADDRNOTAVAIL`, then LaunchAgent recovered and status returned `ok`.
## 下一步执行建议
### P6.16 Task Artifact UX and Failure Messages
### P8.1 Queue Lease / Stuck Run Recovery
-H5 code-run 增加用户可见状态:
- queued / running / validation / succeeded / failed
- 显示“正在执行代码任务”而不是普通连接态
- 失败原因分层:
- 执行器失败
- 产物校验失败
- 超时
- 队列积压或 guard 暂停
- 产物规范从 receipt 扩展到任务级:
- 页面编辑任务声明目标 public HTML
- 仓库/文件任务声明目标相对路径
- 无明确目标的通用 code-run 继续使用 receipt 兜底。
- P6.16 完成并稳定后,再评估 worker 并发是否从 1 提到 2。
-`running` run 增加 lease / stale recovery:
- worker 启动和轮询时识别超过 TTL 的 running run。
- 将超时 running 标记 failed 或 retryable,避免 worker/进程异常退出后永久卡住
- guard 同步读取 stale running 作为暂停依据。
- 增加只读检查脚本输出:
- oldest running age
- stale running count
- recovery dry-run actions
- 同时修补 Portal auth/session DB 瞬时错误:
- `read EADDRNOTAVAIL` 不应作为 uncaught exception 杀掉 Portal
- session attach 失败应降级为 503/401 或跳过认证态,而不是进程退出
### P6.19 Task-level Artifact Validation
- receipt 继续作为兜底。
- 页面编辑任务追加目标 `public/*.html` 校验。
- 文件/仓库任务根据任务参数声明目标相对路径。
### P6.22 Task Artifact UX and Failure Messages
- 用户侧显示 queued/running/validation/succeeded/failed。
- 失败原因分层展示。
@@ -24,6 +24,8 @@
- P6.12 All-user Long-running Gray: 已完成,生产已默认对所有用户开启 H5 code-run 灰度,external worker running,普通测试用户真实 code-run 已成功生成 MindSpace 产物。
- P6.13 Agent Run Auto-pause Guard: 已完成,新增 `agent-run-guard.mjs` 和 LaunchAgent,按失败数/队列积压/running 超时自动关闭 code-run gate 并停 worker。
- P6.15 H5 Code-run Validation Metadata: 已完成,H5 code-run 自动声明 `.memind/agent-runs/<requestId>.json` receipt 校验,生产已恢复 `MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION=1` 并通过普通测试用户真实路径。
- P6.17 Controlled Worker Concurrency Canary: 已完成,external worker 短窗口提升到并发 2,两条真实 code-run 同时 running 并全部通过 receipt validation。
- P6.18 Concurrency Rollout Policy: 已完成,生产 worker 和 Portal runtime/status 已对齐到并发 2worker KeepAlive 保持开启,保留回滚备份。
- P5.15 Active Stream TTL Reconcile: 已按用户要求跳过,暂不做报表/定时 reconcile。
- P5 Worker Pool 运维化: 已完成第一步,Redis Router 支持 worker drain。
- P5.9 First-token Latency EWMA: 已完成,StreamController 会把首个 SSE chunk 延迟写入 RedisSLO 报告已展示。
@@ -2642,6 +2644,98 @@ runtime/status:
- `/Users/john/Project/memind_backups/20260702-114335-p615-validation-metadata`
- worker KeepAlive 运维补强备份: `/Users/john/Project/memind_backups/20260702-115330-worker-keepalive`
### 2026-07-02 P6.17 Controlled Worker Concurrency Canary
目标:
- 在 required validation 和 auto-pause guard 已稳定后,短窗口验证 external worker 并发 2。
- 不扩大 code-run gate,不改用户 allowlist,不改 task type allowlist。
- 真实 canary 使用两个新测试用户,避免同一 MindSpace/git 工作目录互相锁住。
生产变更:
- 备份:
- `/Users/john/Project/memind_backups/20260702-120520-p617-concurrency-canary`
- worker LaunchAgent 临时提升:
- `MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2`
- `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2`
- `--limit 2`
- `KeepAlive=true`
验证:
- 两条真实 code-run 同时进入 running:
- run `d064c8c0-b061-4df7-8c9b-5dfa315271ea`
- user `916f1fe6-e9c8-44b5-9faa-2fc1bf146ab9`
- request `p617-concurrency-20260702040600-1`
- started `1782965163186`
- completed `1782965180346`
- status `succeeded`, attempts `1`
- run `64717bcc-4065-4947-a0d3-a706f3b62640`
- user `07f29934-8cf8-408a-af92-3c4276e579c8`
- request `p617-concurrency-20260702040600-2`
- started `1782965163135`
- completed `1782965186566`
- status `succeeded`, attempts `1`
- 两条 run 都写入:
- `tool_gateway_dispatch`
- `tool_gateway_result`
- `tool_gateway_validation`
- `succeeded`
- MindSpace 验证:
- 两个 receipt JSON 均包含 requestId。
- 两个 `public/p617-concurrency-*.html` 均包含目标 marker。
- worker log:
- `limit=2`
- `maxConcurrentRuns=2`
- `dispatched=2`
- P6.17 后复查:
- worker running
- queue empty
- guard `shouldPause=false`
- SLO `ok=true`, `failures=[]`
### 2026-07-02 P6.18 Concurrency Rollout Policy
目标:
- 将 P6.17 的并发 2 从短窗口 canary 固化为当前 all-user gray 的可运营策略。
- 让 worker LaunchAgent、Portal `.env` 和 runtime/status 对齐,避免状态面显示并发 1 但实际 worker 并发 2。
生产配置:
- `/Users/john/Project/Memind/.env`:
- `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2`
- `MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2`
- worker LaunchAgent:
- `MEMIND_AGENT_RUN_QUEUE_CONCURRENCY=2`
- `MEMIND_AGENT_RUN_WORKER_BATCH_SIZE=2`
- `--limit 2`
- `KeepAlive=true`
验证:
- `https://mm.tkmind.cn/api/status` 返回 `ok`
- `/api/runtime/status`:
- `codeRunPolicy.requireValidation=true`
- `toolRuntime.queue.maxConcurrentRuns=2`
- `toolRuntime.queue.statusCounts={}`
- worker check:
- running `true`
- process args include `--limit 2`
- guard dry-run:
- `ok=true`
- `shouldPause=false`
- queue empty
- SLO:
- `ok=true`
- `failures=[]`
观察:
- Portal 在一次重启窗口中出现 `read EADDRNOTAVAIL` 并由 LaunchAgent 自动拉起,随后 `/api/status``/api/runtime/status` 恢复 `ok`
- 后续建议优先做 running/stuck recovery 与 DB/session auth 异常不致命化,避免瞬时 DB/socket 错误扩大为进程退出。
## 回滚策略
- P0: 修改前保留 `server.mjs` 备份;如启动失败,恢复备份并 `launchctl kickstart` Portal。