Files
mi-fitness-health/docs/nas/backend-query-review.md
T

74 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后端汇总与分页:最终审查及交付
日期:2026-10-17。状态:实现、本机验证、各任务审查及最终跨模块审查通过;2026-10-17 15:25用户交互部署成功。
主目录:D:\CodeProject\mi-fitness-health;分支nas-health;最终产品代码提交317194c(最后一提交仅为QA截图采样修正,产品实现截至6292755,部署脚本截至ecbd485)。本记录提交只更新文档,不改候选镜像、发布包或产品。
本机:85项Python、53项Node、7/30天八类页面、四身份原生附件、隔离容器验证完成。性能范围和限制见 backend-query-validation.md。90万心率旧响应73569039字节,新首屏3570字节;这不是NAS耗时测量。统计/图表/每页10条明细由服务器返回,CSV双端流式,不在浏览器构建全量数组。
离线包:artifacts/query-summary/release;tar SHA256为2aeb958f5251d25a8d749f289c725cbb38043e7e687c0cef1c2dce6c063509b9,manifest SHA256为a1a2d51843b4b3b5bbf71bbfb38c8ca87ab2733f83d41e7b1c875641f63e346e。已本机复核全部9项发布哈希,未带Deploy参数。
仅拟替换健康backend/web为local/mi-fitness-nas:20261017-summary8,worker保持audit3;原密码来源、数据库和密钥挂载、日历及端口不变,失败尝试回退。正式更新前仍需用户明确批准,并在本机交互终端输入sudo密码。
兼容副本已同步13个文件、0删除;最终复核0文件需更新,未覆盖并发修改。未推送网络仓库。
已知边界:一次早期浏览器采集只有Uncaught文本、没有堆栈;增强记录后的两轮完整验收未再现,原证据保留,未宣称修复。窄屏头部拥挤是保留的原样式。SQL仍随样本数扫描;大数据NAS查询耗时尚未实测。同刻多设备体重使用明确的稳定主键次序,个别latest可能与旧未定义次序不同,均值/样本集合不变。
## 最终独立审查原文
# 整分支最终独立审查
范围:`497fd1c..317194c21c51373b82decb351840ea9985dd349a`,分支 `nas-health`。首先阅读已批准的 `docs/nas/backend-query-design.md`、`docs/superpowers/plans/2026-10-17-backend-query-summary.md`,继而核对各任务已通过审查、最终验证记录、整分支产品/部署差异与直接调用方。本轮重点为跨模块集成,未重复局部全量审查或测试。
**Spec verdict:APPROVED。**
**Quality verdict:APPROVED。** 未发现本次引入且需要阻塞交付的新缺陷,无 must-fix。
## 跨模块证据
| 核查项 | 结果与位置 |
| --- | --- |
| 筛选集合贯通 | `storage/view_queries.py:95` 的共享 CTE 统一用户、北京时间范围、心率类型、小睡和压力等级,之后再取最近 N 条/最新记录。`:190`、`:219`、`:257`、`:264` 的统计、图表、分页总数及导出复用同一选择。`web_assets/static/js/health-ui.js:23` 为首屏、records、export 构造同一日期/筛选参数,导出不携带当前 page。 |
| 统计及前端消费 | `services/view_query_service.py:17` 输出统计、coverage、points 和 page;`health-views.js:128` 直接消费服务端统计,不以当前 10 条重算均值。分页 detail 使用 page.total 与当前 rows,`health-ui.js:88` 仅替换明细并在总数减少时回退有效末页。`app.js:374` 单次 overview 请求的字段与服务端 `view_query_service.py:31` 一致。睡眠实睡回退、缺失值、样本均值和体重全部测量均值保持设计口径。 |
| SQLite 一致性和排序 | `view_queries.py:86` 显式 query_only/BEGIN,`view_query_service.py:17` 将首屏所有读取置于同一事务;分页另开短事务。所有读取按真实整秒、小数秒、id 排序;北京时间归日避免 SQLite 毫秒舍入跨午夜。`storage/__init__.py:269` 最终关闭连接;未改数据库结构或同步写入实现。 |
| 旧响应与日历 | `health-ui.js:67` 的当前查询判断包含请求编号、类型、日期与筛选;`:88` 又核对分页编号和当前 model。日历晚到只作用于当前 model,并使用最新页码/rows 重绘。overview 另有请求编号与范围保护。已有前端测试明确覆盖这些交错路径。 |
| 查询/导出身份一致 | `app.js:152` 与 `health-ui.js:110` 共用 getHeaders:state Key 优先、输入框回退。浏览器 Key 用临时同源 POST 表单提交并立即清除;无 Key 保留原生 GET。`web.py:156` 和 `:180` 对服务器 Key 统一优先,并按大小写无关方式去除旧头,避免摘要/导出用户不同。POST 只对白名单导出转换为无 body GET。 |
| Origin 与授权 | `web.py:68` 的既有 Host、Basic、Origin 检查仍先于代理执行;新 API 仍经过全局 `_gate`(`api.py:176`),并由 `_resolve_context`(`:243`)解析身份。Key 未进入导出 URL,响应头白名单不回传鉴权头;after_request 保留 no-store。 |
| 双端流生命周期 | `api.py:978` 在每个导出的单一线程内创建、推进和关闭迭代器,取消时关闭任务排入原线程且不被 shutdown 丢弃;`:1003` 在发送失败/断开时显式 aclose。`view_queries.py:264` 分批 fetchmany(256),finally 关游标。`web.py:195` 的 finally 与 `:203` 的 call_on_close 分别覆盖已消费及未开始消费的响应;没有全量 CSV 缓冲。正在执行的 SQLite 读取可先完成再关闭,是已有明确边界。 |
| 部署范围 | 对照既有 `deploy/compose.override.yml` 与 `deploy/query-summary/compose.override.yml`,除注释外仅 backend/web 镜像不同;worker、端口、密码来源、日历挂载相同,数据库挂载继承未改的 base compose。`update-health.sh:54` 只对 backend/web 使用 `up --no-deps --no-build --pull never`,另比较其他健康服务 id/image。`:50` 安装回退 trap,保留旧配置与镜像。 |
| 发布身份与生产核对 | `update-health.sh:25` 严格验证去末尾 CR/LF 后的 digest,仅接受同包索引/配置身份。`check-ready.py:35` 仅取 OpenAPI paths 元数据,不发健康查询/导出;资源、代理、匿名拒绝、挂载/端口和日历检查符合批准边界。最终截图提交仅改 QA,产品、镜像与发布包未因截图采样变化。 |
上述产品路径均相对于 `src/mi_fitness_mcp/`。
## 采信的验证及本轮检查
- 已核对 `docs/nas/backend-query-validation.md`、task-4-report.md、task-1-review.md、task-2-review.md、task-3-fix-1-review.md、task-4-fix-1-review.md,并阅读对应流式、分页测试和一致性入口的直接证据。
- 采信最终已有 **85 Python + 53 Node**、真实浏览器 16 视图与四种身份原生附件、独立 Linux 容器、合成 1x/10x 和发布身份/就绪模型验证。本轮没有重跑这些已有效的检查,也未把这些数字称为本轮执行结果。
- 本轮实际执行 `git diff --check 497fd1c..317194c`,exit 0;读取时 HEAD 为 `317194c21c51373b82decb351840ea9985dd349a`,工作区干净。未发现需要额外最小复现的具体产品疑点。
## 已知边界与交付结论
- 同刻体重旧 oracle 72.9、新稳定 id 次序 72.91 是已批准的规格差异,记录集合及均值不变,不列为回归。
- 首轮 Uncaught 缺 stack 无法归因,随后增强观测两轮未复现;继续保留其记录,不宣称已修复,也不单凭该历史事件要求重跑所有验收。
- SQLite 范围扫描仍随样本规模增长;90 万心率的本机统计仍约 8.3 秒。首屏约 3.6 KB 证明传输有界,不证明 NAS 即时响应。已有窄屏控件拥挤和依赖弃用警告不扩大处理。
- **NAS 未部署。** 本审查批准本机实现和可审阅发布候选,不代替仅替换 backend/web 的用户部署确认,也不声称 NAS 引擎导入已实测。
- 本轮仅新增本报告;未改产品、QA、部署源、发布包、Git index 或 HEAD;未连接 NAS,未读取真实健康记录、数据库或凭据。
## 执行中作出的决定(完整记录)
Ruling: Tool rejected a fresh implementation agent with thread limit reached. Reuse idle implementation agent with a fresh task brief, retain separate read-only reviewer — no close-agent capability is exposed — cost if wrong: more context carryover; narrow task scope and independent review mitigate it.
Ruling: CSV iteration must use one dedicated worker thread (including SQLite iterator creation/next/close), with async chunk delivery — SQLite connections are thread-bound and event-loop SQL would stall unrelated requests — cost if wrong: an extra worker per active export; no full-result buffering and lifecycle tests bound the cost.
Ruling: Preserve selected client identity for CSV via a same-origin POST form and export-only proxy adaptation — ordinary attachment links cannot send X-API-Key and returning a full Blob violates bounded browser memory — cost if wrong: a narrowly scoped POST download branch; test auth/Origin/GET compatibility and no Key in URL.
Ruling: For equal-instant body measurements, latest uses the approved time/id DESC order (synthetic tie72.9 vs72.91 now chooses72.91), not the old API's unspecified tie order — freeze the oracle, compare unambiguous fixtures and test ties separately — cost if wrong: one tied measurement may differ from old display; sample set and mean remain unchanged, report explicitly.
## 正式部署结果
2026-10-17 15:25:38(北京时间),用户已批准仅更新健康backend/web并在本机输入sudo密码。部署入口exit_code=0,安装器的镜像身份、资源、认证、OpenAPI元数据、只读挂载及worker容器未重建检查通过。后续只读复核覆盖配置SHA256为054b4541a3a2e50d46473061822c637c4694fa210414d05b2b6aa43deabea0d3,与发布包一致;worker状态ok、最近成功日期2026-10-17,calendar目录存在。
backend/web为local/mi-fitness-nas:20261017-summary8,worker为20261017-audit3。网址仍为http://192.168.31.201:18322/,用户名admin、原自设密码。未运行NAS合成/压力/健康导出测试;此前本机性能测量不冒充NAS速度。现有发布包的expected-current.sha256仍锁定升级前配置,用于防重复覆盖,不应直接拿旧包再次安装当前版本。