The bounced contract still looked for the old chart calls. The research script now writes to a temp directory unless --out is set. Quota splits stay unimplemented. Co-Authored-By: Grok (agent loop)
91 lines
7.1 KiB
Markdown
91 lines
7.1 KiB
Markdown
# PROGRESS · 合盘排盘与报告多余子进程(2026-10-15)
|
||
|
||
- 分支:`codex/api-chart-subprocess-gate-20261013`
|
||
- 实际基线:`origin/staging` `9274491681f6fcacbc87e3797441d2c5221de874`(任务书写的 `77057a819` 更早)
|
||
- `scripts/jyotish_api_server.py`:开工 10944 行,做完 10940 行
|
||
- BUG-1333、BUG-1334。`docs/BUG_HISTORY.md` 后半是同一份历史的副本,两处都补上了。
|
||
|
||
## 做了什么
|
||
|
||
1. 合盘两次排盘都带 `skip_vedastro_main_entry_overview: true`,不改 `synastryBirthPayload`。两张盘和婚恋分支的两张九分盘都改成同时发出。任一失败仍走原来的 `catch`。
|
||
2. 前端 `app/api` 和 `lib` 里发往 `/api/chart` 的请求体必须带这个开关。白名单是空的。
|
||
3. 父进程先看一次能不能导入 PyJHora。不能就不起年度回放和 Tajika 的子进程,返回和「子进程在没装时」相同的结果。样本在 `tests/fixtures/api-chart-subprocess-gate/`,来自本机真实子进程(当时 `find_spec("jhora")` 为 `None`)。装了之后仍走子进程。
|
||
4. 解释器查找(含「没找到」)和静态 oracle 校验在进程内各记一次。校验按文件路径、mtime、大小作键。不缓存出生资料。
|
||
5. 开关 `JYOTISH_GATE_CHART_OVERVIEW` 默认关。只有把它设为 `1` 时,不带 skip、也不是异步排队的 `/api/chart` 才占一个重计算名额。`/api/chart` 没有加进 `HEAVY_COMPUTE_PATHS`。预热咨询不占名额的判断挪进了闸门模块。
|
||
6. 名额占满时打一行日志:被拒路径、当前占用者路径、已占秒数。不写请求正文。
|
||
|
||
## 自测
|
||
|
||
| 检查 | 命令 | 结果 |
|
||
| --- | --- | --- |
|
||
| 闸门、增长护栏、本单新测试 | `.venv\Scripts\python.exe -m pytest tests/test_api_chart_subprocess_gate.py tests/test_api_heavy_compute_gate.py tests/test_api_server_growth_contract.py -q` | 21 passed,退出码 0 |
|
||
| 报告三份既有测试 | 同上解释器 `-m pytest tests/test_report_reader_main.py tests/test_report_longform_parity.py tests/test_report_density_facts.py -q` | 27 passed,退出码 0 |
|
||
| 前端本单与相关单文件 | 在 `frontend` 下 `node node_modules/tsx/dist/cli.mjs --test tests/synastry-chart-skip.test.ts tests/chart-request-skip-contract.test.ts tests/chart-view-route.test.ts tests/ephemeris-route.test.ts` | 22 pass,0 fail |
|
||
| 类型检查 | `frontend\node_modules\.bin\tsc --noEmit -p frontend` | 退出码 0 |
|
||
| lint | 在 `frontend` 下 `npm run lint` | 退出码 0,0 error,123 条原有 warning |
|
||
| A/B | `.venv\Scripts\python.exe scripts\research\api_chart_subprocess_ab.py` | 退出码 0。数字见下 |
|
||
|
||
`grep` 这三个名字在 `tests/` 里只命中本单新测试:`annual_pyjhora_replay`、`_oracle_progress_snapshot`、`_resolve_external_pyjhora_python`。
|
||
|
||
## A/B 数字
|
||
|
||
合盘:串行不带 skip 中位 8.0596 秒、2 次 `subprocess.run`;并发带 skip 中位 0.0166 秒、0 次。盘面摘要逐字节一致。耗时约为对照的 0.2%。
|
||
|
||
报告:强制仍起子进程中位 16.5322 秒、7 次;短路后 15.3235 秒、1 次。去掉易变字段后逐字节一致。少掉的 6 次是年度回放和 Tajika。
|
||
|
||
名额模拟(种子 64,一分钟,未改规则):
|
||
|
||
| 方案 | 咨询被拒 | 报告被拒 | 校正被拒 | 最高并发 | 碰到不得加池的那条 |
|
||
| --- | --- | --- | --- | --- | --- |
|
||
| O1 现状 | 40% | 0% | 17% | 2 | 否 |
|
||
| O2 咨询单独小池 | 0% | 0% | 17% | 3 | 是 |
|
||
| O3 咨询最多再等 1.5 秒 | 30% | 0% | 33% | 2 | 否 |
|
||
| O4 重任务最多占 1 个 | 0% | 0% | 67% | 2 | 否 |
|
||
|
||
全文在 `docs/testing/api-chart-subprocess-gate-ab-20261013.md`。
|
||
|
||
## 改既有断言
|
||
|
||
无。原值 / 新值 / 原因:没有改旧断言。
|
||
|
||
## 偏离
|
||
|
||
- `/api/health` 没有加 `heavy_compute` 字段。状态函数 `heavy_compute_status()` 在闸门模块里,接到健康检查会让主文件变长。任务书允许砍掉这一项。
|
||
- 星盘名额开关默认关。打开会让不带 skip 的外部调用可能拿到 429,任务书要求先有 A/B 再提议,本单不打开。
|
||
- O2、O3、O4 没有实现。
|
||
- 报告对照不是 staging 源码另导入,而是本分支把「已安装」强制打开。静态校验缓存两边都在,所以耗时差只反映那 6 个子进程。
|
||
- 合盘子进程是 2 → 0,不是任务书举例的 4 → 0。这台机器两张盘合计只数到 2 次 `subprocess.run`。
|
||
- 没有「装了 PyJHora」的计时。父进程强制当成已安装时,子进程仍会因为没装而失败,这一组用来代表「不短路就要付启动开销」。
|
||
|
||
## 环境缺口
|
||
|
||
- 本机 `.venv`:`sys.executable` 是工作树的 `python.exe`;`shutil.which("python3")` 是 Windows 应用商店占位;`python3.14` 没有;`find_spec("jhora")` 是 `None`。
|
||
- Docker 在,没有本地 `jyotisha-api` 镜像,镜像里的解释器路径没有核实。
|
||
- 生产装了 VedAstro、并且开了外网时,不带 skip 的排盘真实耗时本机测不到。
|
||
- 名额被占满后连带拒绝的真实频率,要等日志上了 staging 再看。
|
||
|
||
## 需拍板
|
||
|
||
轻重任务要不要分开限流,本单不改。模拟里,让咨询少被拒,校正就会多被拒;给咨询单独开池会让同时在跑的个数超过 2。要改规则需要另立一单。
|
||
|
||
## 默认值
|
||
|
||
- `JYOTISH_GATE_CHART_OVERVIEW` 默认关。
|
||
- 合盘 skip 和报告短路没有开关。
|
||
|
||
## 2026-10-15 打回修复
|
||
|
||
合盘路由的合同跟上了新写法:仍锁本人和对方各请求一次排盘,并锁住关闭外部概览。对照脚本默认写到系统临时目录,只有带 `--out` 才写指定文件,不再覆盖已入库的记录。业务代码没改。名额配额仍不实现。没有新 bug 编号,补在 BUG-1333 的两处副本上。
|
||
|
||
| 检查 | 命令 | 结果 |
|
||
| --- | --- | --- |
|
||
| 用户数据合同 | `.venv\Scripts\python.exe -m pytest tests/test_supabase_user_data_contract.py -q` | 8 passed,退出码 0 |
|
||
| 脚本默认路径 | 调用 `resolve_record_path` | 默认不在仓库内,也不是已入库的 json;`--out` 指向传入路径 |
|
||
| 源码文本检索 | `tests` 与 `frontend/tests` 里的合盘路由、`postPython("/api/chart"`、`postPython("/api/varga_full"` | 只有这一条合同在断言旧写法,已改。其它命中是在读路由文件,没有断言旧的两次调用。分盘前缀仍匹配,没改 |
|
||
| 类型检查 | 在 `frontend` 下 `node_modules\.bin\tsc --noEmit -p .` | 退出码 0 |
|
||
| lint | 在 `frontend` 下 `npm run lint` | 退出码 0,0 error,123 条原有 warning |
|
||
|
||
原值:`postPython("/api/chart", selfPayload)` 与 `postPython("/api/chart", partnerPayload)`。新值:两次调用都展开对应 payload,并带 `skip_vedastro_main_entry_overview: true`。原因:合盘改为同时排两张盘并关掉用不上的外部概览,合同要锁住这两次请求和这个开关,不放宽。
|
||
|
||
偏离:先合并了 `origin/staging` `1de3cc307be9134a3b8d1d606c738c1468414118`。相对打回 SHA `336286e4`,`frontend/src` 里多出来的是数据访问层那一单,不是这次修复改的。技能目录下的同名脚本没改,它的输出根不是仓库的 `docs/testing`。
|