feat: establish production SaaS foundation

This commit is contained in:
Codex
2026-07-12 19:26:57 +08:00
parent 1c2ce38cea
commit 39f7332f33
219 changed files with 20647 additions and 2628 deletions

View File

@@ -0,0 +1,106 @@
# 单租户 10 万学生容量验证手册
本工具用合成数据验证租户后台学生列表在单租户最多 100000 名学生时的 PostgreSQL 查询形状、cursor 分页和子串搜索。它不会连接 API直接使用与 `GET /api/tenant-admin/students` 相同的 SQL 核心和下列索引:
- `idx_memberships_student_keyset_page`
- `idx_platform_users_identity_search_trgm`
## 安全边界
- 只能用于 `local` / `test` / `ci` 数据库,且 `app_private.environment_safety.allow_destructive_tests` 必须为 `true`
- 任何写入、基准或清理模式都必须显式传入 `SMOKE_SEED_LOCAL_OR_CI_ONLY`
- 租户 slug 必须以 `capacity-test-` 开头。如果同名租户没有匹配的 `metadata.capacityHarness` 标记,工具会拒绝使用它。
- 合成用户同时使用 `legacy_id``raw_profile.capacityHarness` 标记。清理前如果发现真实 `auth_user_id`、其他租户 membership、租户 owner 或专用租户中的非 harness membership工具会拒绝操作。
- 禁止使用 `tikupro-pg` 或任何生产数据库。当前本机 `127.0.0.1:5432` 映射到 `tikupro-pg`,因此工具也会对 localhost/loopback 的 5432 端口在连接前硬拒绝。本工具的本地结果 is not a production SLA。
不要为了跑工具而在现有服务器数据库上修改环境标记。应该新建专用的非生产 PostgreSQL/Supabase 实例,运行全部迁移,再设置测试环境标记。
## 1. 先看计划
默认模式不连接数据库、不写数据:
```bash
npm run perf:tenant-students:plan
```
如果希望在计划中显示脱敏后的 host / port / database / user可以同时提供 `DATABASE_URL`;工具不会输出密码。
## 2. 小规模 smoke
以专用隔离库为例smoke 使用独立的 `capacity-test-students-smoke` 租户生成 250 名学生,执行 5 组查询、写出 JSON/Markdown 证据,然后在成功或失败路径清理专用租户和合成用户。它不会清理 `capacity-test-students-100k` 中人为保留的基准夹具。
```bash
DATABASE_URL='postgresql://postgres:postgres@127.0.0.1:55432/postgres' \
npm run test:tenant-students:capacity:smoke
```
报告默认保存到已忽略的 `docs/refactor/performance-reports/`。smoke 返回后应确认 `cleanup.deletedTenant=1``cleanup.deletedUsers=250`
## 3. 生成 10 万行并跑基准
`run` 会保留夹具,便于重复采样或查看查询计划:
```bash
DATABASE_URL='postgresql://postgres:postgres@127.0.0.1:55432/postgres' \
npm run perf:tenant-students:run -- \
--count=100000 \
--batch-size=10000 \
--iterations=20 \
--warmup-iterations=3 \
--confirm=SMOKE_SEED_LOCAL_OR_CI_ONLY
```
写入是 set-based 的 `generate_series` + UPSERT每批在独立事务中完成。同一个 count 可重复执行;如果已有夹具行数高于新 count工具会要求先清理避免隐式删数据。
正式上线证据应使用一次性 `evidence` 模式,它会在同一个受保护流程中完成 seed、benchmark、cleanup并把清理结果与四类残留计数写入同一份 JSON
```bash
DATABASE_URL='<target-spec-isolated-clone-url>' \
npm run perf:tenant-students:evidence -- \
--count=100000 \
--batch-size=10000 \
--iterations=20 \
--warmup-iterations=3 \
--confirm=SMOKE_SEED_LOCAL_OR_CI_ONLY
```
`evidence` 模式成功时必须包含 `cleanup.cleanupVerified=true`,且 `remaining.tenants/platformUsers/memberships/profiles` 全部为 `0`
每组证据包含:
- 实际 `platform_users` / `tenant_memberships` / `student_profiles` 行数。
- 工具内部记录的 seed / benchmark / cleanup / total 阶段耗时。
- 首页和约 90% 深度 cursor 页。
- 姓名、手机号、email substring 搜索。
- 应用端观测 P50/P95以及每组 SQL 的 `EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)`
- 实际使用的 plan node、index name、shared/local/temp buffer 摘要与完整 JSON plan。
## 4. 重复基准
```bash
DATABASE_URL='postgresql://postgres:postgres@127.0.0.1:55432/postgres' \
npm run perf:tenant-students:benchmark -- \
--iterations=30 \
--confirm=SMOKE_SEED_LOCAL_OR_CI_ONLY
```
深 cursor 使用约 90% 位置的真实 `(created_at, membership_id)` 锚点,不使用 OFFSET 制造查询。
## 5. 清理
```bash
DATABASE_URL='postgresql://postgres:postgres@127.0.0.1:55432/postgres' \
npm run perf:tenant-students:cleanup -- \
--confirm=SMOKE_SEED_LOCAL_OR_CI_ONLY
```
清理只会命中:
- `slug=capacity-test-students-100k` 且带匹配 `metadata.capacityHarness` 的专用租户。
- `raw_profile.capacityHarness.namespace=tiku.student-capacity.v1` 且 tenant slug 相同的合成用户。
自定义租户名时,六个命令都必须传入同一个 `--tenant-slug=capacity-test-...`
## 验收口径
这个工具首先是数据量和查询计划验证,不应单独用它承诺线上 SLA。正式验收还需要在与生产同规格的非生产环境复跑并与 API 并发压测、PostgreSQL 调优证据、连接池和云盘 I/O 指标一起归档。