Loader waits for a module another thread is still importing (issue #132, BUG-1482 reopened)
Independent Staging Quality Gate / validate (push) Successful in 16m40s
Independent Staging Quality Gate / publish (push) Successful in 4m32s

Gate run 5888 failed: the synastry full dossier computes two full readings
on a thread pool, and the second thread got jyotish_engine from sys.modules
while the first was still executing it (no cmd_full_reading yet). Reuse now
goes through importlib.import_module, which waits on the module lock.

Four threads loading one module in a fresh interpreter: before
[False, True, True, True], after all True three times. Dossier scenario
before 4/4 AttributeError, after 6/6 ok; synastry-full-report.test.ts 17/17.
Ledger ERR-117: local npm baseline hid it (system python3 lacks swisseph).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jesse_Chen
2026-10-28 13:47:30 +08:00
co-authored by Claude Opus 5.5
parent cd6ad9d27a
commit a614895a2b
5 changed files with 42 additions and 1 deletions
+2 -1
View File
@@ -20235,7 +20235,7 @@
## BUG-1482 | 排盘服务的加载器给同一个 Python 文件另起一份私有副本,缓存互不相通
- 状态:resolved(代码 + 回归测试;待部署)
- 状态:resolved(2026-10-28 复发一次后再修;代码 + 回归测试;待部署)
- 首次发现 / 最近更新: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 份)。每份都有自己的模块级缓存,彼此不相通,多占内存、多算一遍。
@@ -20247,6 +20247,7 @@
- 关联:#133(重计算多进程)。
- 复发自:无
- 修复版本:分支 `codex/local-module-reuse-20261028`。
- **2026-10-28 复发(staging 门禁 run 5888 失败)**:现象:前端测试「a public pair dossier fills every section without birth keys」报 `AttributeError: partially initialized module 'jyotish_engine' has no attribute 'cmd_full_reading'`。触发条件:合盘全档案用线程池同时算两个人的完整解读,两个线程同时第一次经加载器拿 `jyotish_engine`。根因:本条第一次修复让加载器直接返回 `sys.modules` 里的同一文件;A 线程正在执行这个模块的 import 时,它已经在 `sys.modules` 里但还没执行完,B 线程拿到的是半成品。旧的私有副本写法每个线程各执行一份,不会交出半成品。修复:复用 `sys.modules` 里的模块时也经 `importlib.import_module`,它会在模块锁上等另一线程执行完。验证:新增 `tests/test_local_module_reuse_20261028.py::test_two_threads_loading_one_module_both_get_it_fully_initialized`(新进程里 4 个线程同时起跑载入,修前 `[False, True, True, True]`,修后 3 次都全 True);本机按门禁的同一段代码构造合盘全档案,修前 4/4 报同一个错,修后 6/6 通过;前端 `synastry-full-report.test.ts` 17 条全过(本机把 `python3` 指到项目 venv 才能跑)。为何当时没拦住:本机全量前端测试里这条一直失败(系统 `python3` 没有 Swiss Ephemeris),被我当作「基线失败」比对掉了,见错误台账 ERR-117。
## BUG-1483 | 月亮恰在星宿起点时 Yogini 第一大运余额变成约 0
+1
View File
@@ -243,6 +243,7 @@ For large architecture or release work, also read:
| ERR-077 | VedAstro request previews serialized the live `x-api-key` header, allowing logs and failed test output to expose credentials. | resolved; credential rotation required 2026-07-16 | Preview/metadata profiles never contain authentication headers. Inject `VEDASTRO_API_KEY` only immediately before network execution; rotate any key exposed before this fix. |
| ERR-078 | On this macOS host, bare `python3` resolves to Python 3.9 without pytest, while the project requires Python >=3.11 and uses PEP 604 annotations. The pre-work launcher previously reused that incompatible interpreter for every child check. | resolved 2026-08-07 | `pre_work_check.py` must probe and prefer the repository `.venv` (Python >=3.11 with pytest), expose the selected runtime in its JSON report, and fail closed with setup guidance if no compatible runtime exists. Keep regression coverage for system-Python launch and strict `JYOTISH_PRE_WORK_PYTHON` override behavior. |
| ERR-079 | VedAstro hosted replay and fixed-commit self-host validation cannot run on this host when `VEDASTRO_API_ENDPOINT` / `VEDASTRO_API_KEY` are absent and neither a .NET runtime nor a reachable Docker daemon is available. | observed 2026-07-17 | Keep hosted closure `blocked`; run `vedastro_contract_probe.py --repeats 3` only after injecting credentials through the environment, and build the pinned source in a provisioned Windows/.NET or reachable container environment. Never persist credentials in artifacts or shell history. |
| ERR-117 | Local frontend `npm test` runs tests that shell out to a bare `python3`; on a host whose system Python lacks the project deps (pyswisseph) those tests fail every time, so a baseline diff treats them as "already failing" and hides a real regression (2026-10-28: BUG-1482 race only showed in staging gate run 5888). | observed 2026-10-28 | Run baseline and delivery `npm test` with `PATH=<repo>/.venv/bin:$PATH` so `python3` is the project venv; before calling a frontend failure "baseline", check whether it fails only because of the local Python. After a host restore, rebuild `.venv` (no g++ here: build pyswisseph through a zig c++ wrapper) and run `deploy/patch_vedastro_update_check.py`, or VedAstro auto-update ends processes early. |
## ERR-080 | Issue link was mistaken for benchmark provenance | mitigated 2026-07-18
PyJHora issue #17 is a UI/encoding issue with a general mismatch report, not VP Jain calibration. The benchmark now pins `V4.8.7` / `ca22995709bd60e371e7820a1a5efc80ce4cf821` and the exact test function URL. Treat its AGPL numeric expectations as a candidate replay, never independent formula arbitration.