perf: stabilize real pocketbase import

This commit is contained in:
Codex
2026-06-30 10:50:31 +08:00
parent 3303426806
commit fce5513464
6 changed files with 424 additions and 119 deletions

View File

@@ -13,6 +13,17 @@ Supabase 适合承担 PostgreSQL、RLS、Auth、Edge Functions、Webhook/Hooks
Supabase Auth 可继续作为最终 JWT 用户体系目标;本地重构期先用 `app_private.auth_sessions` 签发 `tk_` session保证 Web/Taro 能跑通端到端流程。
## 本地验收边界
当前阶段没有真实阿里云/腾讯云/微信/QQ/支付宝密钥时,不阻塞后端编码和本地联调。验收重点放在 provider adapter 之外的商用关键链路:
- 短信:使用 `AUTH_SMS_PROVIDER=mock` 或本地 fake endpoint 验证验证码生成、HMAC 存储、冷却、过期、登录事件和 session 签发。生产环境仍为 mock 会 fail-fast。
- 微信小程序/微信网页/QQ 登录:使用本地 fake endpoint 或测试桩覆盖 code 换身份之后的账号创建/合并、`user_identities`、登录审计和 session 签发;真实 `code2Session`、授权回调域名和开放平台错误码到云服务器解析完成后再验收。
- 微信/支付宝支付:本地优先验证下单参数生成、回调验签/解密的错误处理、幂等键、`payment_events`、订单状态、权益开通、退款状态机、补偿 worker 和对账工单。真实商户号、API v3 key、证书、支付宝公私钥和回调域名上线后再做官方联调。
- 密钥:本地可以只写测试密钥或 fake secret但必须走 `app_private.tenant_secrets` / `app_private.platform_secrets` 引用链;前端和 public schema 不允许出现明文密钥。
因此本地“跑通”不等于真实平台验收完成。上线门禁必须再补真实生产账号、真实回调域名、官方账单抽样和生产 provider 配置证据。
## 当前已实现
- `POST /api/auth/sms/send`:手机号验证码发送,验证码只保存 HMAC hash。
@@ -321,6 +332,8 @@ B 端合作商年费、服务费、服务器资源费不走学生端 `orders`
真实接入前需要先明确微信支付、支付宝或聚合支付是否允许你们销售的题库会员形态,以及小程序端是否涉及虚拟支付限制。
本地开发可以先把这些配置留空或配置为 inactive。租户后台保存 provider 配置时只写非敏感公开字段和 `secretRef`;等云服务器域名、备案、官方应用/商户申请完成后,再在租户后台或平台后台写入真实密钥并执行生产联调。
## 需要准备的资料
- 阿里云或腾讯云短信:签名、模板 ID、AccessKey/SecretKey、短信用途文案。

View File

@@ -172,7 +172,7 @@
| --- | --- | --- |
| PocketBase schema/导出分析 | 可联调 | `scripts/import-pocketbase` 支持 schema summary/risk、`npm run pb:import:dry-run` 导出目录静态迁移报告 |
| PocketBase JSON dry-run | 可联调 | 不写数据库检查导出目录、JSON 形态、核心集合、旧 ID、敏感字段、schema relation、未映射集合和关键业务计数`--profile=production` 会额外检查生产迁移必需集合和关键字段覆盖率,正式切换建议配合 `--fail-on-warnings` |
| PocketBase SQLite 标准化导入 | 迁移期 | 已支持真实 SQLite 只读导出后的核心集合标准化,新增覆盖 `user_answer_records -> answer_records/wrong_questions``mock_exam_configs -> practice_blueprints``referral_qrcodes -> referral_qrcodes/referral_codes``commission_settings -> tenant_commission_settings`;缺用户订单会进入财务复核且不自动开权益,缺归属手册章节会进入“迁移待复核手册”并写 `pb_import_issues`全量真实导入仍需继续做批量化性能优化 |
| PocketBase SQLite 标准化导入 | 可联调 | 已支持真实 SQLite 只读导出后的核心集合标准化,新增覆盖 `user_answer_records -> answer_records/wrong_questions``mock_exam_configs -> practice_blueprints``referral_qrcodes -> referral_qrcodes/referral_codes``commission_settings -> tenant_commission_settings`干净本地 Supabase 全量真实导入 248555 条记录约 8 分 58 秒,`pb:import:validate` 为 0 failures、3 warnings缺用户订单会进入财务复核且不自动开权益,缺归属手册章节会进入“迁移待复核手册”并写 `pb_import_issues`正式切换前仍需人工处理 7 个已支付缺用户订单和 22 个待复核手册章节 |
| 题目 JSON preview/import | 可联调 | 后端负责规范化、issue、幂等、审计 |
| 公共题库采纳、手动同步和自动同步 | 可联调 | 平台授权后,租户可采纳公共题库并复制已发布题目快照;同步 API 和 `public-banks` worker 支持新增/更新题目、重新校验授权、跨租户拒绝、审计记录、租户内容通知和租户自改冲突保护;冲突处理 API 已支持单条/批量采纳平台版本和保留租户本地版本worker 失败会写 `public_question_bank_sync_failed` 租户通知并保留稳定错误码,恢复成功会自动关闭失败通知;平台可通过 `/api/platform-admin/question-bank-sync-status` 查看跨租户同步运营状态;已覆盖跨租户、重复采纳、采纳后组卷、同步新增题、通知隔离/已读/自动 resolved、冲突不覆盖、单条/批量冲突处理、worker 自动同步/失败通知/恢复关闭、starter 单地区不可见/不可采纳第二地区题库、pro 全国套餐可见第二地区题库等测试 |
| 单词 JSON preview/import | 可联调 | 兼容旧模板 |
@@ -220,3 +220,15 @@ git diff --check
- smoke seed
- API build
- API integration tests
真实迁移专项最近已通过:
```bash
npx supabase db reset
$env:DATABASE_URL='postgresql://postgres:postgres@127.0.0.1:54322/postgres'
npm run pb:import:json
npm run pb:import:validate
npm run check:importer
```
结果:`pb:import:json` 用时约 8 分 58 秒,`pb:import:validate` 为 0 failures、3 warnings。`npm run pb:import:dry-run -- --profile=production --json` 仍按预期返回非 0因为真实旧数据还有 30 个订单缺 `userId` 和 22 个手册章节缺 `subjectId` 两个上线前 blocker。

View File

@@ -78,7 +78,8 @@
- 已补 `npm run pb:import:dry-run` 静态迁移报告工具、`--profile=production` 生产迁移门禁、关键集合/关键字段覆盖率检查、strict warning 门禁测试和真实数据迁移验收 runbook真实 SQLite 已导出 58 个业务 collection、248555 条记录,并跑过 production dry-run。
- 当前真实 dry-run 剩余 blocker30 个订单缺 `userId`,其中 7 个 paid22 个知识手册章节缺 `subjectId`。导入器已补隔离策略:缺用户订单进入财务复核且不自动开权益,缺归属手册章节进入“迁移待复核手册”。正式切换前仍必须人工找回/确认这些记录。
- 已补真实 mapper gap`user_answer_records` 85442 条标准化到 `answer_records/wrong_questions``mock_exam_configs` 48 条标准化到 `practice_blueprints``referral_qrcodes` 79 条标准化到 `referral_qrcodes/referral_codes``commission_settings` 1 条标准化到 `tenant_commission_settings`
- 真实 `pb:import:json` 试跑已验证 raw 导入和新 mapper 开始落库,但 248555 条真实记录的逐条标准化仍超过 10 分钟,需要下一阶段继续做批量化/事务分批优化,重点是 `questions``question_versions``user_answer_records``pb_raw_records`
- 真实 `pb:import:json` 已在干净本地 Supabase 上跑通248555 条真实记录导入约 8 分 58 秒;`pb:import:validate` 为 0 failures、3 warnings。核心落库计数3670 用户、74102 题目、85199 旧答题记录、38205 错题、636 订单、447 权益、48 个模考蓝图、79 个推广码、1 条租户分佣设置
- 最新导入 run 剩余 29 个 critical import issues7 个已支付订单缺用户、22 个手册章节缺所属手册,均为正式切换前人工复核项;旧答题记录空用户或旧用户已删除已降为 warning。
- 处理完 blocker 后再跑 `npm run pb:import:dry-run -- --profile=production --json --fail-on-warnings`,再跑 `pb:import:json``pb:import:validate` 和业务抽样。
- 对题目 JSON、单词、知识手册、分数线、视频走后端 preview/import API 做二次验证。
@@ -103,6 +104,7 @@
- 已完成阿里云短信、腾讯云短信 adapter 的后端实现和本地 fake endpoint 测试。
- 已完成微信小程序 `code2Session` 登录主链路。
- 已完成手机号绑定/换绑、微信网页登录、QQ 登录基础 API继续补真实生产账号、回调域名和开放平台联调。
- 本地阶段不等待真实密钥,继续用 mock/fake provider 验证验证码、账号合并、登录审计、session 签发和错误处理;真实密钥、合法域名和开放平台错误码等上云后再联调。
- 旧 PocketBase 用户账号和新身份体系的映射/补绑。
3. 导入体系扩展
@@ -136,7 +138,7 @@
8. 订单和营销体验
- 已完成订单详情、订单状态轮询、激活码预检查、优惠券前台领取、下单抵扣计算、优惠券复杂规则、核销明细/报表和内部退款状态机。
- 已完成支付/退款补偿 worker、官方账单下载 worker、资金对账导入比对、差错工单、异常订单运营台和人工调整凭证复核Taro 财务运营台第一版已接入;继续补学生端售后入口深化、营销活动 UI、真实生产账单格式抽样验收和活动效果看板。
- 已完成支付/退款补偿 worker、官方账单下载 worker、资金对账导入比对、差错工单、异常订单运营台和人工调整凭证复核Taro 财务运营台第一版已接入;本地继续验证回调后业务链路、幂等、审计、权益开通/撤销和密钥不泄露,真实生产账号、回调域名和账单格式抽样验收上云后补齐;继续补学生端售后入口深化、营销活动 UI 和活动效果看板。
9. 积分和反馈增强
- 已完成每日签到、积分流水、反馈提交、租户后台处理、奖励积分幂等。
@@ -252,6 +254,6 @@
2. 继续补 Taro 学生端旧体验:地区选择、刷题答题卡、后端权威断点续练、本地进度恢复、模拟倒计时、主观题后端自评、阅读理解/案例分析多小题、视频播放、反馈、模考报告、逐题复盘、错题/收藏专题、个人中心学习报告、收银台、订单详情、售后入口、站内消息筛选/已读/归档、积分任务/兑换/积分明细、题干/解析/知识手册 RichContent 安全渲染、H5 KaTeX 公式渲染、私有资源 ID 题图短签名、背单词卡片学习/发音/收藏练习、资料短签名水印预览/下载确认已接第一版;继续补小程序公式真机验收、题图资源字段化、独立消息中心增强、背单词更细统计、小程序支付容器、分享场景和状态管理。
3. 补平台后台增强:租户基础资料编辑增强、平台审计告警升级策略、平台催缴通知配置操作台细节和平台在线收款。
4. 云服务器部署 Supabase/PostgreSQL 和 API配置对象存储生产环境变量`check:refactor` 的远程等价测试。
5. 使用 `F:\project\参考\旧题库数据库文件` 中的真实 PocketBase 数据,按 `docs/refactor/pocketbase-real-data-migration-runbook.md` 做 production dry-run导入演练、校验和抽样验收;导入过程中发现的字段污染、跨集合引用断裂、敏感字段和旧权限问题都要沉淀到 importer mapper 或修复脚本,不手工临时修库。
5. 使用 `F:\project\参考\旧题库数据库文件` 中的真实 PocketBase 数据,按 `docs/refactor/pocketbase-real-data-migration-runbook.md` 继续做人工复核和抽样验收;当前 dry-run/导入/校验链路已跑通,下一步重点是 7 个已支付缺用户订单、22 个待复核手册章节、2533 道旧分类缺失题目和 5298 条引用已删除题目的答题记录的运营处理结论。导入过程中发现的字段污染、跨集合引用断裂、敏感字段和旧权限问题都要沉淀到 importer mapper 或修复脚本,不手工临时修库。
6. 并行补真实登录、真实生产账单格式验收、异常订单运营台、对象存储真实 AV/内容安全服务联调、转码/CDN 级水印/生命周期、题库导出模板精排/操作台、公共题库生产定时调度和失败告警。
7. 前后端联调通过后,再做支付、权限、数据导入、资料下载、视频播放的商用验收。

View File

@@ -143,7 +143,7 @@ auxiliary.db: _logs 121715 条,仅摘要
当前导入器已经补齐下面 4 个旧集合的标准化 mapper
- `user_answer_records` 85442 条会导入到 `answer_records`,并按错误记录重建 `wrong_questions`
- `user_answer_records` 85442 条会导入到 `answer_records`,并按错误记录重建 `wrong_questions`旧用户为空或旧用户已不存在的答题记录会跳过并写 warning不作为财务/权益级 blocker。
- `mock_exam_configs` 48 条会导入到 `practice_blueprints(mode='mock_exam', assembly_type='filters')`
- `referral_qrcodes` 79 条会导入到 `referral_qrcodes`,并同步补 `referral_codes`
- `commission_settings` 1 条会导入到 `tenant_commission_settings`
@@ -158,7 +158,38 @@ production dry-run 还有这些 warning属于运营处理项
- `dashboard_cache`、空 `customer_messages/smscodes/tenant_config` 可不作为正式数据源,必要时只保留审计摘要。
- `recent_practices` 和少量 `user_answer_records` 有旧用户引用断裂,需要在导入后复核 `pb_import_issues`
性能注意:真实 `pb:import:json` 试跑已经证明 248555 条真实记录会超过 10 分钟。正式迁移前需要继续优化 importer 的批量写入和分批事务,重点是 `pb_raw_records``questions/question_versions``user_answer_records`。迁移演练必须记录总耗时、每阶段耗时和失败恢复策略。
最新真实导入演练结果:
```text
环境:本地 Supabase先执行 npx supabase db reset
命令npm run pb:import:json
耗时:约 8 分 58 秒
导入后校验npm run pb:import:validate => 0 failures, 3 warnings
核心计数:
platform_users: 3670
questions: 74102
answer_records: 85199
wrong_questions: 38205
orders: 636
entitlements: 447
practice_blueprints(mode=mock_exam): 48
referral_qrcodes: 79
tenant_commission_settings: 1
```
最新导入 run 的 `pb_import_issues` 仍有 29 个 critical需要正式切换前人工复核
- 7 个 `orders` 已支付订单缺用户:订单会进入财务复核,不自动开通权益。
- 22 个 `handbook_chapters` 缺所属手册:章节会挂到“迁移待复核手册”。
导入后校验的 3 个 warnings 当前含义:
- 2533 道题保留 `legacy_category_id` 但无法解析到旧 `categories/module_nodes`,原始 `categoryId``nodeId` 相同,且旧导出中已没有对应分类或节点。不能由导入器硬绑到错误分类,需后续按科目/题型人工归档或在内容后台批量挂载。
- 5298 条旧答题记录保留 `legacy_question_id` 但无法解析到题目,说明旧学习日志引用了已删除/未导出的题目;这些记录不会进入错题本有效组卷。
- 最新 run 存在 29 个 critical import issues即上面的付费订单和手册章节人工复核项。
性能注意:真实 `pb:import:json` 已能在 9 分钟左右完成 248555 条真实记录导入。后续若题库规模继续增长,仍建议继续批量化 `questions/question_versions` 并补阶段耗时统计、失败恢复和断点重跑策略。
## 阶段 1静态 Dry-Run
@@ -265,6 +296,12 @@ Remove-Item Env:\FAIL_ON_WARNINGS
- `tenant_settings.public_config` 不含密钥。
- `crm_config.secret_ref` 只引用 `app_private.tenant_secrets`
当前演练可接受但上线前必须确认的 warning
- 已支付订单缺用户不能自动开权益,必须由财务/运营确认是否补绑用户、退款、作废或保留售后台账。
- 手册章节缺归属需要内容负责人确认归并到正确手册,或保留在迁移待复核手册并在前端隐藏。
- 已删除分类下的题目和已删除题目对应的学习记录,需要按运营口径决定是否建立“迁移待复核分类”、按科目批量归档,或仅保留 legacy trace。
## 阶段 4抽样验收
每次演练都应至少抽样下面数据: