docs(tasks): 星盘页与 VedAstro 外网调用脱钩 + 运行期真相两单
星盘页首屏那一发 /api/chart 没传 skip_vedastro_main_entry_overview, 本机实测冷算 0.40–0.66 秒里约 0.36 秒是 VedAstro 空转(连 endpoint 都 没配的情况下);带标志的同一调用是 5 毫秒。生产 env 开着 network 与 fanout,等于首屏同步等 24 个外部请求加 3 次领域扫描,而前端 mapper 与 contract 根本不读这份证据。BUG-718,复发自 BUG-161。 运行期单记录两条新发现:官方 vedastro==1.23.25 其实是 REST 客户端, 且 import 时请求 pypi 并 pip install --upgrade 自升级(实测 pin 装完 一 import 即变 1.23.26);无 key 时免费层排队是同步 sleep 加进程级 全局锁,24 个请求约 4.8 分钟堵住前台线程。台账补 ERR-107 / ERR-108, 生产 env 核对清单交产品负责人执行。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
This commit is contained in:
co-authored by
Claude Fable 5
parent
69ede4367f
commit
ce1939b074
@@ -285,3 +285,19 @@ Prevention: 构建与测试 runner 不得与其他服务共用宿主文件系统
|
||||
`docker compose --project-name jyotisha-postgres-* up -d --wait postgres` 报 `failed to create network …_app: all predefined address pools have been fully subnetted`。Docker daemon 正常,本机同时存在着十余个遗留 `jyotisha-postgres-*-postgres-1` 与 `jyotisha-local-preview-postgres-1`。`npm run test:db --test-concurrency=1` 仍每测新建 compose 项目网络。咨询上下文单未做 `docker network prune`(会清共享宿主资源)。
|
||||
|
||||
Prevention: 需要真实库测时先清本任务自己的 fixture 网络,或在默认 `bridge` 上起一次性 Postgres 做迁移语法检查;不得把地址池耗尽写成「本机无 Docker」。新迁移至少用 `psql --set ON_ERROR_STOP=1 -f` 在可写实例上跑通 ALTER/GRANT。
|
||||
|
||||
## ERR-107 | 官方 `vedastro` Python 包是 REST 客户端,且 import 时联网自升级,运行期版本与 `requirements.txt` 的 pin 不一致 | observed 2026-09-15
|
||||
|
||||
`requirements.txt:9` 固定 `vedastro==1.23.25`,`deploy/railway-api.Dockerfile` 在镜像里 `pip install -r requirements.txt`。把该版本装进本机 `.venv` 拆开后确认:整包 46 KB,`vedastro/calculate.py` 的每个方法都汇到 `requests.post("https://api.vedastro.org/api/Calculate/<method>", timeout=120)`,`vedastro/__init__.py` 的自述是 `# VedAstro Python Library - REST API Mode`,**包内没有任何本地天文计算**。因此 `vedastro_python_bridge.py` / `vedastro_official_capability_runner.py` 这条「官方 SDK 路径」与 `vedastro_service_adapter.py` 的 `urlopen` 路径打的是同一个外部 API,不是本地算力。
|
||||
|
||||
更要紧的是 `vedastro/update_check.py`:`__init__.py` 在导出任何符号之前调用 `check_for_update("vedastro")`,它请求 `https://pypi.org/pypi/vedastro/json`(5 秒超时),发现有新版就直接 `subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "vedastro", "--quiet"])`。本机实测:装 1.23.25 后第一次 import 即被升级为 1.23.26。于是每次 spawn bridge 子进程都要付一次 pypi 往返;容器文件系统可写时 pin 会在运行期漂移,而这个包的内容直接决定发给外部 API 的请求形状。
|
||||
|
||||
Prevention: 不得把 `vedastro` 当作本地计算能力来源,也不得用它的存在证明「外部引擎已本地闭环」——它不可用时只等于外部 API 不可达。镜像必须中和 `check_for_update`(patch 失败即构建失败),并有测试断言运行期 `importlib.metadata.version("vedastro")` 等于 `requirements.txt` 的 pin。评估任何第三方 SDK 前先看它 import 期做了什么;import 期联网或改写自身环境的包一律按外部依赖审。关联 BUG-089(CI 自动升级 MCP 打破固定版本,同族)。
|
||||
|
||||
## ERR-108 | VedAstro 免费公共模式的排队是同步 sleep + 进程级全局锁,24 个请求的取证会把前台线程堵住数分钟 | observed 2026-09-15
|
||||
|
||||
`scripts/vedastro_service_adapter.py` 的 `_acquire_free_tier_slot()`(第 1877 行)在命中官方公共 endpoint 且 `VEDASTRO_API_KEY` 为空时,持 `_FREE_TIER_REQUEST_LOCK`(第 358 行)`time.sleep()` 等名额;配额默认 5 个 / 60 秒(第 354–355 行)。有 key 才走 `api_key_present` 分支不排队。
|
||||
|
||||
一次 official full snapshot 的请求清单实跑 `_official_full_snapshot_manifest` 数出来是 24 个(`events_overview` 1 + `dasha_all` 1 + `chart_core` 10 + `house_core` 12),fanout 开关 `VEDASTRO_FULL_SNAPSHOT_FANOUT_ENABLED` 的代码默认值就是 `"1"`(第 2520 行)。24 ÷ 5 个每分钟 ≈ 4.8 分钟,期间该进程所有 VedAstro 调用被同一把锁串起来;生产是 2 vCPU 单进程。参照延迟:本机单次 `api.vedastro.org` 往返 0.38 秒,快速模式(fanout 关)一次完整 snapshot 3.65 秒 `status=ok`。生产在国内 VPS,真实 RTT 未测,上述数字只是下限。
|
||||
|
||||
Prevention: 前台同步路径不得进入无上限排队,超预算即 fail-fast 降级并让调用方看出是限流而非「服务不可用」;排队总预算必须可配且默认不超过 `VEDASTRO_TIMEOUT_SECONDS`。不得靠调大免费层配额绕过——那是第三方的额度。判断「VedAstro 慢」之前先确认当前是不是无 key 的免费公共模式,以及 fanout 是否开着;两者都属于运行期 env 真相,不能从代码默认值推定。关联 BUG-065、BUG-161、BUG-718、BUG-720。
|
||||
|
||||
Reference in New Issue
Block a user