From c0258c1859498b905f6b99733e21e31fe2582054 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 1 Jul 2026 08:14:26 +0800 Subject: [PATCH] docs: align web launch checks and postgres tuning --- README.md | 2 +- docs/refactor/postgresql-4c16g-tuning.md | 15 ++++++++++++++- docs/refactor/taro-h5-deployment.md | 2 +- docs/refactor/web-launch-acceptance-checklist.md | 2 +- scripts/product-scope-guardrails-test.js | 9 +++++++++ 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aab09c63..d4cec37a 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ npm run smoke:taro:h5:interaction `taro-route-contract-test` 会校验 `apps/taro/src/app.config.ts`、真实 `pages/**/index.tsx`、启动页三端跳转、H5 静态烟测入口和前端交接文档中的页面引用保持一致。新增或删除页面时必须同步路由和文档,避免 H5/小程序构建后才发现入口漂移。 `taro-api-contract-test` 会比对 `apps/taro/src` 中所有 `apiRequest('/api/...')` 调用与 `apps/api/src/features/*/index.ts` 注册路由,阻断前端调用不存在 API、method 写错或绕过统一 `/api` 命名空间的漂移;动态导入和少量 server alias 需要在脚本 allowlist 中显式声明。 `taro-persona-contract-test` 会从学生、租户管理员、平台管理员三类前端视角检查关键页面、路由和服务调用,阻断刷题、会员订单、错题收藏、学生运营、内容导入、营销财务、租户设置、平台租户账务和公共题库授权入口被误删或漂移。 -`smoke:taro:h5:interaction` 会启动三套 H5 发布产物、本地 mock API 和本机 Chrome/Edge,在真实浏览器里点击学生首页、题库、答题、收藏、错题/收藏复习、背单词、知识手册、资料短签名和水印、视频播放授权、分数线、AI 择校、消息中心、会员收银台下单/支付参数/订单状态,租户后台六个主模块,以及平台后台四个主模块,用来补足静态烟测无法发现的 H5 运行时空白页、history 路由和点击事件问题。 +`smoke:taro:h5:interaction` 会启动三套 H5 发布产物、本地 mock API 和本机 Chrome/Edge,在真实浏览器里点击学生首页、题库、答题、收藏、错题/收藏复习、背单词、知识手册、资料短签名和水印、视频播放授权、分数线、AI 择校、消息中心、会员收银台下单/支付参数/订单状态,租户后台内容导入、公共题库采纳/同步/冲突处理、学生运营、营销/CRM/分佣、主题/角色/成员写操作,以及平台后台租户、账务、公共题库授权和员工写操作,用来补足静态烟测无法发现的 H5 运行时空白页、history 路由和点击事件问题。 H5 线上推荐每个静态目录放独立 `runtime-config.json` 覆盖公开配置,避免 API/Auth 域名变化时重打包: diff --git a/docs/refactor/postgresql-4c16g-tuning.md b/docs/refactor/postgresql-4c16g-tuning.md index 238feba0..bf635c70 100644 --- a/docs/refactor/postgresql-4c16g-tuning.md +++ b/docs/refactor/postgresql-4c16g-tuning.md @@ -12,7 +12,7 @@ - PostgreSQL 官方 WAL/Checkpoint:https://www.postgresql.org/docs/current/runtime-config-wal.html - PostgreSQL 官方 Connections:https://www.postgresql.org/docs/current/runtime-config-connection.html -说明:postgresqlco.nf 的 tuning guide 适合作为 `postgresql.conf` 参数分类和调参入口参考;具体参数语义、重启要求、风险边界和版本差异仍以 PostgreSQL 官方文档为准。当前 Codex 环境直接访问 `https://postgresqlco.nf/tuning-guide` 会返回 403,因此落地值不直接抓取该站页面,而是把它作为导航来源,并以 PostgreSQL 官方文档、本项目真实压测结果和上线可观测性共同校验。 +说明:postgresqlco.nf 的 tuning guide 适合作为 `postgresql.conf` 参数分类和调参入口参考;具体参数语义、重启要求、风险边界和版本差异仍以 PostgreSQL 官方文档为准。如果当前网络环境无法直接打开 `https://postgresqlco.nf/tuning-guide`,不要用第三方转载内容直接替代生产参数,应继续以 PostgreSQL 官方文档、本项目真实压测结果和上线可观测性共同校验。 ## 适用前提 @@ -23,6 +23,19 @@ 如果 PostgreSQL 是唯一重负载服务,可以使用下方 `dedicated-db` 值;如果 API/worker/Nginx 也在同机,先使用 `shared-host` 值。 +## 2026-07-01 调参复核结论 + +本轮按 postgresqlco.nf 的参数导航重新对照 PostgreSQL 官方文档后,保留当前 `shared-host` profile,不把 4 核 16G 机器简单按“数据库独占”调满。原因: + +- `shared_buffers`:官方文档说明专用数据库服务器可从约 25% 内存起步,超过 40% 通常不一定更好,因为 PostgreSQL 仍依赖操作系统缓存。同机还要运行 Supabase/API/worker/Nginx,因此 `shared-host=3GB` 比 4GB 更保守;独立数据库主机才使用 `dedicated-db=4GB`。 +- `effective_cache_size`:它只是 planner 对共享缓冲和 OS cache 的估算,不会真实预留内存。`shared-host=10GB` 用来引导 SSD 上合理使用索引,但上线后必须结合 `EXPLAIN (ANALYZE, BUFFERS)` 与慢 SQL 复核。 +- `work_mem`:官方文档强调它是每个排序/哈希操作的基准,不是每个连接的总内存。后台报表、导入和复杂查询可能一次使用多份 `work_mem`,所以 `16MB` 是上线起步值,不建议在未观察 temp file spill 和 OOM 风险前直接放大。 +- `maintenance_work_mem` / `autovacuum_work_mem`:导入、建索引和 vacuum 会受益,但 autovacuum 多 worker 并发时可能叠加占用内存,因此保留 `512MB/256MB`。 +- `random_page_cost=1.1`:SSD 云盘下可以鼓励索引扫描,但官方文档也提示 planner cost 没有统一理想值,不能只凭单个查询实验盲调。上线后以真实慢 SQL、缓存命中和查询计划为准。 +- `max_connections=80`:4 vCPU 不靠大量直连抗并发,优先控制 API/worker 连接池和 Supabase pooler。连接数放大只会把数据库推向上下文切换、锁等待和内存压力。 + +本地 DB 受限压测已经证明:只限制容器 CPU/内存但不调 PostgreSQL 参数时,系统可以保持 0 错误,但 P95 延迟不满足上线门禁。因此生产验收必须按“调参证据 + API 阶梯压测 + 慢 SQL/pg_stat_statements”闭环完成,而不是只填一组参数。 + ## 推荐起步值 | 参数 | shared-host 起步值 | dedicated-db 起步值 | 说明 | diff --git a/docs/refactor/taro-h5-deployment.md b/docs/refactor/taro-h5-deployment.md index 440ef1f9..97c6375d 100644 --- a/docs/refactor/taro-h5-deployment.md +++ b/docs/refactor/taro-h5-deployment.md @@ -197,7 +197,7 @@ H5 正式回归时建议把前端登录态切到 Supabase Auth,并观察业务 node scripts/taro-h5-release-guardrails-test.js --require-dist ``` - `smoke:taro:h5` 会用临时静态服务器检查三套 H5 产物可托管、资源可加载、history fallback 可用,并用 mock API 验证租户解析契约。`smoke:taro:h5:interaction` 会用真实 Chrome/Edge 打开三套发布产物并点击学生刷题/收藏/会员、租户题库内容/财务、平台租户/账务中心关键路径;若服务器没有默认浏览器,可设置 `TARO_H5_SMOKE_BROWSER=/path/to/chrome`。`manifest:taro:h5` 会生成三套 H5 的部署清单,包含构建命令、发布目录、入口路由、`index.html` hash、资源数量、runtime-config 是否存在、租户解析模式和公开配置状态。发布守卫会检查三套 H5 产物是否存在 `index.html`,源码和产物是否混入 `x-user-id`、`x-platform-admin-key`、PocketBase 引用、数据库连接串、服务端密钥形态,并检查运行时配置示例只包含公开字段。若还没有把真实 `runtime-config.json` 放入静态目录,会显示 warning;正式发布前必须在每个 H5 目录根部补齐该文件。 + `smoke:taro:h5` 会用临时静态服务器检查三套 H5 产物可托管、资源可加载、history fallback 可用,并用 mock API 验证租户解析契约。`smoke:taro:h5:interaction` 会用真实 Chrome/Edge 打开三套发布产物并点击 32 项关键路径:学生刷题、收藏、错题/收藏复习、背单词、知识手册、资料、视频、分数线、AI 择校、消息、会员下单和订单状态,租户后台内容导入、公共题库采纳/同步/冲突处理、学生运营、营销/CRM/分佣、主题/角色/成员写操作,以及平台后台租户、账务、公共题库授权和员工写操作;若服务器没有默认浏览器,可设置 `TARO_H5_SMOKE_BROWSER=/path/to/chrome`。`manifest:taro:h5` 会生成三套 H5 的部署清单,包含构建命令、发布目录、入口路由、`index.html` hash、资源数量、runtime-config 是否存在、租户解析模式和公开配置状态。发布守卫会检查三套 H5 产物是否存在 `index.html`,源码和产物是否混入 `x-user-id`、`x-platform-admin-key`、PocketBase 引用、数据库连接串、服务端密钥形态,并检查运行时配置示例只包含公开字段。若还没有把真实 `runtime-config.json` 放入静态目录,会显示 warning;正式发布前必须在每个 H5 目录根部补齐该文件。 写入 `production-launch-evidence.json` 的正式证据必须使用严格模式,确保三套发布目录都已放置真实公开 `runtime-config.json` 且没有 warning: diff --git a/docs/refactor/web-launch-acceptance-checklist.md b/docs/refactor/web-launch-acceptance-checklist.md index d918b977..5dbd37d4 100644 --- a/docs/refactor/web-launch-acceptance-checklist.md +++ b/docs/refactor/web-launch-acceptance-checklist.md @@ -90,7 +90,7 @@ node scripts/taro-h5-release-guardrails-test.js --require-dist npm run smoke:launch-persona ``` -`smoke:taro:h5` 会启动临时静态服务器和 mock API,验证三套 H5 的 `index.html`、JS/CSS 资源、history fallback、公开 runtime config 和 `/api/tenant/resolve` 契约。`smoke:taro:h5:interaction` 会在真实 Chrome/Edge 中点击学生、租户后台、平台后台关键路径,覆盖静态烟测发现不了的 JS 运行时、直接 history 路由刷新和 Taro 点击事件问题;当前脚本覆盖 26 项检查,包括学生首页、题库、答题、收藏、错题/收藏复习、背单词、知识手册、资料短签名和水印、视频播放授权、分数线、AI 择校、消息中心、会员收银台下单/支付参数/订单状态,租户后台六个主模块,以及平台后台四个主模块。`taro-h5-release-guardrails-test` 会扫描源码、三套 H5 产物和 runtime-config 边界,防止旧 PocketBase、`x-user-id`、`x-platform-admin-key`、数据库连接串和服务端密钥形态进入前端发布目录。若刚构建完但未放入真实 `runtime-config.json`,脚本允许 warning;正式部署目录必须补齐。 +`smoke:taro:h5` 会启动临时静态服务器和 mock API,验证三套 H5 的 `index.html`、JS/CSS 资源、history fallback、公开 runtime config 和 `/api/tenant/resolve` 契约。`smoke:taro:h5:interaction` 会在真实 Chrome/Edge 中点击学生、租户后台、平台后台关键路径,覆盖静态烟测发现不了的 JS 运行时、直接 history 路由刷新和 Taro 点击事件问题;当前脚本覆盖 32 项检查,包括学生首页、题库、答题、收藏、错题/收藏复习、背单词、知识手册、资料短签名和水印、视频播放授权、分数线、AI 择校、消息中心、会员收银台下单/支付参数/订单状态,租户后台内容导入、公共题库采纳/同步/冲突处理、学生运营、营销/CRM/分佣、主题/角色/成员写操作,以及平台后台租户、账务、公共题库授权和员工写操作。`taro-h5-release-guardrails-test` 会扫描源码、三套 H5 产物和 runtime-config 边界,防止旧 PocketBase、`x-user-id`、`x-platform-admin-key`、数据库连接串和服务端密钥形态进入前端发布目录。若刚构建完但未放入真实 `runtime-config.json`,脚本允许 warning;正式部署目录必须补齐。 写入生产上线证据时,三套正式发布目录必须先放入真实公开 `runtime-config.json`,再运行严格模式: diff --git a/scripts/product-scope-guardrails-test.js b/scripts/product-scope-guardrails-test.js index 27a27d68..7cabe814 100644 --- a/scripts/product-scope-guardrails-test.js +++ b/scripts/product-scope-guardrails-test.js @@ -10,8 +10,10 @@ const scannedDocs = [ 'docs/refactor/backend-handoff-roadmap.md', 'docs/refactor/legacy-feature-gap-matrix.md', 'docs/refactor/next-development-todo.md', + 'docs/refactor/taro-h5-deployment.md', 'docs/refactor/taro-frontend-integration.md', 'docs/refactor/taro-production-integration-checklist.md', + 'docs/refactor/web-launch-acceptance-checklist.md', ]; function readLines(relativePath) { @@ -53,6 +55,13 @@ for (const item of lines) { if (/前端消息中心/.test(text) && hasAny(text, [/仍缺/, /待补/, /未完成/, /缺/])) { failures.push(`${item.file}:${item.line} 学生前端消息中心已经完成第一版,不能继续写成待补:${text}`); } + + if ( + /smoke:taro:h5:interaction/.test(text) && + hasAny(text, [/26 项/, /租户后台六个主模块/, /平台后台四个主模块/, /租户题库内容\/财务、平台租户\/账务中心/]) + ) { + failures.push(`${item.file}:${item.line} H5 交互烟测已经覆盖 32 项和后台真实写操作,不能回退到旧描述:${text}`); + } } assert.deepEqual(failures, [], `Product scope guardrails failed:\n${failures.join('\n')}`);