10 KiB
10 KiB
id, title, phase, deps, status, created, issue, context_ref, claim_branch, work_branch, write_paths
| id | title | phase | deps | status | created | issue | context_ref | claim_branch | work_branch | write_paths | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| T-014 | 建立 Sense 本地 16 路批量收敛与容量基线 | 2 |
|
DOING | 2026-08-08 | 47 | 8ebb8ced49 |
claims/T-014 | agent/codex/T-014 |
|
问题 / 背景
T-006 已证明一台准入实机与四条独立合成源可以完成五路实验室闭环,T-011/T-012 已实现 PostgreSQL Control API、最多 128 项批量期望态、多实例 fencing、孤儿安全闸和低基数指标;但 M2 的默认 16 路仍只有产品配额和单元测试,没有通过真实 HTTP 控制面完成 16 路创建、批量启停、MediaMTX 收敛、局部故障恢复和资源观测。项目当前没有客户网络环境,WireGuard T-013 暂缓,不能让该外部依赖阻塞本地软件容量基线。
本任务建立可重复的 Windows 本地 16 路实验室基准。它验证当前机器、固定软件版本和低码率无人物合成负载下的 Sense/PostgreSQL/MediaMTX 控制面与媒体拉流能力,不代表 16 台真实摄像头、客户网络、存储、AI/GPU 或生产 SLA。
关联需求与交互(如适用)
- 用户故事:US-001、US-002、US-008、US-009;验证默认 16 路站点的批量接入与运维收敛基础。
- 交互清单:IX-003、IX-004、IX-015、IX-016 的后端容量证据;不修改已确认 HTML 原型。
- 相关页面 / 路由:复用冻结的 7 个
/api/v1Control API endpoint、/metrics、MediaMTX v3 API;不增加公共接口。
方案
- 新增
Sense/scripts/t014-capacity.ps1一键基准:校验冻结的 PostgreSQL 17.10、MediaMTX v1.19.3、FFmpeg 与 Go,使用随机回环端口和系统临时目录启动隔离 PostgreSQL、源 MediaMTX、生产 MediaMTX 与 Sense。migration 只读取并重放现有001~011,不修改或连接本机已有D:\pgsql17\data/5432。 - 先用 FFmpeg 生成 640×360、10 fps、H.264、无音频、无人物的短循环媒体夹具,再启动 16 个独立 FFmpeg
-c copyRTSP publisher,每路有独立进程与 Path,可单独停止/恢复。预编码发布避免把 16 路软件编码开销计入 Sense/MediaMTX 基线;不把同一 publisher fan-out 冒充独立源。 - 在临时 PostgreSQL 中建立固定实验室 Tenant/Site/Area,Site 配额精确为 16;运行时生成 Control API opaque token、SHA-256 注册表和 cursor key,文件只存在于临时目录。通过真实 HTTP API 创建 16 个 disabled 视频设备、批量启用并收敛后,验证第 17 个 enabled 同站点设备稳定返回
quota_exceeded且不写入台账;disabled 台账项不冒充已占用通道。 - 使用真实
devices:batchDesiredState和每台设备最新 ETag 执行 16 路批量启用、批量停用、再次启用;每次要求 operation 的 16 个结果全部成功。分别验证生产 MediaMTX 配置/运行 Path 为 16、0、16,设备最终状态与 generation/observed generation 收敛,unconverged=0。 - 在再次启用后同时停止固定四个 publisher,要求能观察到局部离线/未收敛且其余路径继续在线;恢复四个独立进程后自动回到 16 路在线和
unconverged=0。不得通过改数据库、人工编辑 MediaMTX 配置或重建进程集合掩盖失败。 - 正式稳定观察默认 30 分钟、每 10 秒采样。记录 Sense 与生产 MediaMTX 的归一化 CPU、working set、private bytes、handle 峰值,PostgreSQL连接峰值,以及 MediaMTX aggregate inbound bytes/吞吐、在线 Path、Sense 低基数指标和未收敛数。功能正确性有硬门禁;机器相关资源值只记录,不设置伪通用阈值。
- 脚本输出不含 token、DSN、端口清单、Path/source URI 或客户信息的 JSON 摘要;支持显式输出到仓库外路径。失败不输出成功结论,finally 停止全部叶子进程、停止临时 PostgreSQL并校验清理路径;可选调试短窗口必须标记
formal_eligible=false,不得作为正式验收。 - 将正式运行的硬件/软件版本、命令、功能时间、观察样本、资源统计、失败记录、限制和结论写入
docs/research/sense-16-stream-capacity.md,同步 README、架构、路线图和当前状态。增加静态契约测试,锁定 16/17/128/129 语义、无秘密输出、临时目录防护、真实批量 API、独立 publisher 和正式窗口规则。
不可变约束
- 阈值 / 数值边界:正式源数精确为 16;Site 默认配额 16、允许范围 1~128,已有 16 路 enabled 时第 17 路 enabled 必须拒绝,129 仍非法;批量 API 上限保持 128。正式观察不少于 30 分钟、采样周期 10 秒;局部故障固定 4 路且不得影响其余 12 路。短窗口只能 smoke。
- 判定式 / 状态转换:16 个设备先 disabled 创建,随后
16 enabled → 16 disabled → 16 enabled;每轮批量结果必须全部成功。启用完成必须配置 Path=16、运行在线 Path=16、unconverged=0;停用完成必须配置 Path=0、设备 offline 且各自 observed generation 追平。四路故障恢复后必须再次满足 16 路在线和unconverged=0。 - 安全边界:只绑定随机回环端口;运行时 token/cursor key/DSN/临时路径不进入 Git、普通日志或结果摘要。脚本不得读取
ip_camera.env,不得访问客户网络或现有 PostgreSQL data/service;递归清理前必须验证目标位于系统临时目录且名称含 T-014 随机前缀。 - 既有契约:不修改 Control OpenAPI v1、审计 v1/v2、MediaMTX 生成代码或数据库 migration;不把 16 写入业务数组/协议硬上限。T-001/T-006 的实机结论、T-007 真实五上游门禁与未来 T-013 WireGuard 均保持独立。
验收要点
- 任务相关验证:先以短窗口运行脚本 smoke,再执行默认不少于 30 分钟的正式 16 路基准;验证 16 个独立 publisher、第 17 路 enabled 配额拒绝、三轮批量状态、16/0/16 Path、四路故障隔离/恢复、最终
unconverged=0和资源摘要。python -m unittest discover -s tests -p "test_sense_capacity_contract.py"锁定脚本安全/语义。 - 完整门禁:
./init.ps1、三条 Python 治理命令、go -C Sense test ./...、go -C Sense vet ./...、go -C Sense build ./...、./scripts/test_postgres.ps1 -PgRoot D:\pgsql17和git diff --check全部通过;本任务不修改 Go 业务代码,但仍回归全部 Sense 包和 PostgreSQL v5。 - 人工 / 设备验收:不需要摄像头、GPU、客户网络或客户数据。任务所有者核对 30 分钟原始 JSON 摘要、进程独立性和报告;真实摄像头/网络验收仍由 T-007/T-013 完成。
- 构建产物:
Sense/scripts/t014-capacity.ps1、docs/research/sense-16-stream-capacity.md、静态契约测试与同步文档;临时二进制、媒体、数据库、凭据和日志运行后删除,不提交。
边界(不改什么)
不实现或验证 WireGuard/T-013、客户网络、真实 16 摄像头、录像、下游 reader、AI 解码/推理、GPU、Bell UI/服务、Outbox relay、告警规则、跨 MediaMTX 分片或 64/128 路容量;不把本机资源样本转换为最低硬件规格或 SLA。本任务不解除 T-007,失败样本不得从报告中删除。
协作约束
- 责任 Agent:由 dispatcher 分配。
- 唯一写入者:同责任 Agent。
- 委派:默认不启用。
- Gitea:任务规格先进入默认分支,再创建唯一 Issue 并回填编号;领取时记录
context_ref、claim / 工作分支和全部允许写路径。
任何新增写路径先检查与其他活跃任务是否重叠;同一时刻只有一个 Agent 修改本任务的 write_paths。T-007 虽为 waiting,但写路径包含 Sense/;T-014 活跃期间不得恢复 T-007。
执行记录
2026-08-08 一分钟端到端 smoke
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -ObservationMinutes 1通过并输出formal_eligible=false:16 个独立 publisher 全部在线,三轮 16 项 batch 均succeeded,配置 Path 为16 → 0 → 16,第 17 路 enabled 返回quota_exceeded且台账仍为 16 项。- 首次启用、停用、再次启用分别在
3.1 s、1.0 s、3.1 s收敛;同时停止四路后1.0 s观察到精确四路受影响、其余 12 路在线,恢复5.2 s。稳定观察60.8 s/6 次采样,最大与最终unconverged均为 0,最终在线 Path 16,aggregate inbound15.432 Mbps,帧错误 0。 - 保留三类脚本修正记录:发布 ZIP 与 EXE 需要不同 SHA-256;disabled 台账不消耗视频运行配额,故第 17 路门禁必须在 16 路 enabled 后验证;PowerShell 对
application/problem+json返回 byte array,需显式 UTF-8 解码后校验稳定code。每次失败均停止并清理临时 PostgreSQL/进程,未拼接成功片段。
2026-08-08 领取任务
- dispatcher
ila将 Issue #47 分配给codex;context_ref为8ebb8ced492c614106e766192c59b7f13fb4ad0f,claim 为claims/T-014,工作分支为agent/codex/T-014。 - 已读回 Issue
status/doing、assignee、dispatcher 发布的完整 CLAIM 与两个分支 SHA;接受 frontmatter 全部写路径。T-007 继续 waiting,本任务期间不恢复,当前无活跃写路径冲突。
2026-08-08 Gitea 映射
- 任务规格通过 PR #46 合入默认分支后创建唯一主 Issue #47;本次只回填双向映射,映射合入并读回前不领取任务。
2026-08-08 任务定义
- 项目负责人确认客户尚未提供网络环境,WireGuard T-013 后置;本任务先建立不依赖客户网络的本地 16 路软件基线。
- 选择 PostgreSQL v5 + 真实 Control API,而不是沿用 SQLite 直接播种,确保实际覆盖 M2 的认证、配额、ETag、批量 operation、调和与 MediaMTX 路径。
- 选择 16 个独立、预编码
-c copy合成 publisher 作为正式可重复负载;T-006 已单独覆盖准入实机,本任务不混入公网摄像头波动,也不把合成结果表述为真实 16 机或生产 SLA。