API loader shares one module object per file (issue #132, BUG-1482)
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 8m49s

_load_local_module always re-executed the file as _jyotish_local_<name>, so
engine, dasha, varga and others ran as extra copies with their own caches.
It now reuses scripts.<name> / <name> when that file is already imported,
else imports it under its plain name so later imports share it; the private
copy remains only as a fallback. Call sites unchanged. Probe after one
consultation and one chart: loader-made copies 19 -> 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jesse_Chen
2026-10-28 12:43:59 +08:00
co-authored by Claude Opus 5.5
parent 0594afcd5c
commit 8a72aa5b44
4 changed files with 73 additions and 0 deletions
+15
View File
@@ -20232,3 +20232,18 @@
- 关联:体检第 16 条(python-hygiene 数量护栏)。
- 复发自:无
- 修复版本:分支 `codex/frontend-dead-files-20261028`(与 #139 同一分支,两个独立提交)。
## BUG-1482 | 排盘服务的加载器给同一个 Python 文件另起一份私有副本,缓存互不相通
- 状态:resolved(代码 + 回归测试;待部署)
- 首次发现 / 最近更新:2026-10-28 / 2026-10-28(issue #118 代码体检第 20 条 → #132)
- 影响面:`scripts/jyotish_api_server.py` `_load_local_module`(97 处调用点不动)。
- 现象:一次咨询加一次排盘之后,同一个文件在进程里有多份:引擎、大运、Narayana、分盘等 19 个文件由加载器以 `_jyotish_local_<名>` 另起一份,又被别处以 `scripts.<名>` 或 `<名>` 正常 import 一份(`dasha_analyzer`、`jaimini`、`jyotish_engine`、`narayana_dasha`、`varga`、`domain_calculation_service` 各 3 份)。每份都有自己的模块级缓存,彼此不相通,多占内存、多算一遍。
- 触发条件:任何一次经由加载器的计算。
- 根因:加载器总是用 `spec_from_file_location` 以私有名字重新执行文件,不看 `sys.modules` 里是否已经有同一个文件。
- 修复:加载器先查 `scripts.<名>`、`<名>` 是否已载入同一文件,有就复用;没有就按普通名字 `import`(脚本目录本来就在 `sys.path` 上),之后别处的普通 import 直接拿到同一份;只有普通名字解析到别的文件时才退回旧的私有副本。只改加载器,不动调用点。普通名字还能被子进程按名字找到(私有名字不能),为 #133 多进程打底。
- 验证:同一段「一次咨询 + 一次排盘」探针:重复文件 32 → 19、多出的副本 38 → 19,加载器造出的私有副本 19 → 0。剩下的 19 份是 `scripts.X` 与 `X` 两种普通 import 并存,与加载器无关,不在本单范围。新测试 `tests/test_local_module_reuse_20261028.py`。凡引用加载器 / 计算服务的 41 个测试文件,改前改后各跑一遍,失败清单一致(都只有 `test_active_rectification_api.py::test_long_real_conversation_reaches_vedastro_after_local_range_is_narrow`,staging 上本来就失败)。`test_api_server_growth_contract.py` 通过。
- 防复发:上述测试断言加载器不再产生 `_jyotish_local_` 副本、与普通 import 拿到同一个模块对象。
- 关联:#133(重计算多进程)。
- 复发自:无
- 修复版本:分支 `codex/local-module-reuse-20261028`。