Files
Jyotisha/PROGRESS-engine-runtime-hygiene-20260901.md
T
Jesse_Chen 124d3990b2
Independent Staging Quality Gate / validate (push) Failing after 12m34s
Independent Staging Quality Gate / publish (push) Has been skipped
fix(api): persist scratch/local and bound heavy compute concurrency
Keep async job and chart-cache files across API recreates, freeze jyotish_api_server.py growth, and fail fast with 429 when rectification or high-rigor compute is saturated.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 06:12:23 +08:00

129 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROGRESS · Python 引擎运行时治理(2026-09-01
工作树:`.worktrees/engine-runtime-hygiene-20260901`
分支:`codex/engine-runtime-hygiene-20260901`
HEAD`80e7736163be684119c03013a07980031468c634`(仍等于 `origin/staging`
未提交、未推送。未改 `frontend/src/app/page.tsx`。未改 `.gitea/workflows/**`。未切分支、未 reset。迁移 squash 按任务书明确延后。
## 任务 1 · api 命名卷
- 容器 `WORKDIR``deploy/railway-api.Dockerfile`):`/app`
- 代码路径:`Path(REPO_ROOT) / 'scratch' / 'local' / ...` → 容器内 **`/app/scratch/local`**
- Compose 卷名:`api_scratch`
- 挂载:`api_scratch:/app/scratch/local``deploy/docker-compose.server.yml` 的 api 服务)
- 项目前缀后的 Docker 卷名:`jyotisha-staging_api_scratch` / `jyotisha-production_api_scratch`
- 向后兼容:首次 `docker compose up` 创建命名卷;当前 overlay 数据本就是易失的,无迁移
**备份结论(已写入 `deploy/README.md`**
- Chart cache`/app/scratch/local/api_chart_cache`,默认 TTL 900s)不值得备份;重建比归档便宜。
- Async / high-rigor job 态(`async_jobs` / `async_jobs.sqlite3` / `high_rigor_jobs`,默认 TTL 3600s)是短生命周期进行中工作,不是恢复单元。
- Staging 加密备份继续只走 `deploy/backup-staging-postgres.sh`。**不要**把 `api_scratch` 加进该脚本。命名卷的唯一目标是容器重建后缓存与进行中任务还在。
**Deploy 脚本:** `run-staging-deploy.sh` / `run-production-deploy.sh` **未改**`docker compose up` 会创建并重新挂上命名卷;现有 `up -d --remove-orphans` 不会 `down -v`
**Staging 实机三条验收(blocked**:需要真正 dispatch 部署后才能 `docker volume ls`、重启 api 证明 `/app/scratch/local` 存活、核对 `/api/health`。Compose 挂载合同已锁在 `tests/test_railway_deployment.py`
## 任务 2 · 冻结 `jyotish_api_server.py`
- 开工 live `wc -l`**11063**(任务书 11035 已过时;出生精度合入后又涨了约 28 行)
- 本轮薄注册后:**11088**
- 合同上限:**11363**11063 + 300 bugfix slack
- 测试:`tests/test_api_server_growth_contract.py`(注释写明新功能必须开模块)
- 已列入 `scripts/run_quality_gate.py` `CORE_PYTEST_TARGETS`
-`AGENTS.md` 第 8 节:`scripts/jyotish_api_server.py` must not grow;新端点/功能落 `scripts/` 模块,主文件只薄注册
## 任务 3 · 重计算并发闸
新模块 `scripts/api_heavy_compute_gate.py`。主文件只 import,并在 `do_POST` 里 acquire/release。`GET`(含 `/api/health` 与 job 轮询)不经过闸门。
- 环境变量 `JYOTISH_HEAVY_COMPUTE_CONCURRENCY`,默认 **2**(对齐 2 vCPU
- `JYOTISH_HEAVY_COMPUTE_RETRY_AFTER_SECONDS`,默认 **2**
- 饱和:fail-fast,不排队。HTTP **429** + `Retry-After` + `error_code=ERR_COMPUTE_BUSY`
**入闸端点**
- `POST /api/rectification/sensitivity_scan`
- `POST /api/active_rectification_events`
- `POST /api/active_rectification_events_v4`
- `POST /api/rectification/v5/candidate-features`
- `POST /api/rectification/v5/score`
- `POST /api/rectification/v5/diagnostics`
- `POST /api/rectification/v5/vedastro-validate`
- `POST /api/dynamic_rectification_opportunities`
- `POST /api/dynamic_rectification_score`
- `POST /api/high_rigor_workflow`
- `POST /api/consultation_workflow`
- `POST /api/professional_reading`
- `POST /api/vedastro/range_scan`
- `POST /api/vedastro_gateway/run`
- `POST /api/vedastro_gateway/jobs/{id}/run`(前缀匹配)
- `POST /api/thematic_report`
**不入闸:** `GET /api/health`、城市/位置解析、job 轮询、`/api/chart`(已有 TTL 缓存 + `JYOTISH_ASYNC_JOB_*` 有界队列;再叠 429 会误伤常规排盘)、问卷、v5 versions、capability/catalog 等轻量路由。
## 验证命令与输出
```text
/opt/anaconda3/bin/python3.12 -m pytest \
tests/test_api_server_growth_contract.py \
tests/test_api_heavy_compute_gate.py -v
```
```text
collected 7 items
tests/test_api_server_growth_contract.py ... [ 42%]
tests/test_api_heavy_compute_gate.py .... [100%]
============================== 7 passed in 0.28s ===============================
```
饱和用例(limit=1):第二个重请求 **429** + `Retry-After: 2` + `ERR_COMPUTE_BUSY`;释放后 200;同期 `GET /api/health``POST /api/location/resolve` 仍 200。
```text
/opt/anaconda3/bin/python3.12 -m pytest tests/test_api_server_security.py -q
# 129 passed, ~90s(仅 datetime.utcnow DeprecationWarning
/opt/anaconda3/bin/python3.12 -m pytest \
tests/test_runtime_security_p0.py \
tests/test_api_server_script_entrypoint.py -q
# 11 passed
/opt/anaconda3/bin/python3.12 -m pytest \
tests/test_api_async_job_contract.py \
tests/test_railway_deployment.py \
tests/test_api_server_security.py::test_health_endpoint_exposes_runtime_accuracy_metadata \
tests/test_api_server_security.py::test_vedastro_range_scan_endpoint_uses_user_birth_and_returns_controlled_blocked_state \
tests/test_api_server_security.py::test_professional_reading_composes_high_rigor_and_gateway \
tests/test_api_server_growth_contract.py \
tests/test_api_heavy_compute_gate.py -v
# 22 passed in 0.38s
```
`python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45``status=pass`
未改前端,故未跑 `npm test` / tsc。未跑完整 `scripts/run_quality_gate.py --profile quick`quick 仍会跑 Next.js test/lint/build;本轮前端豁免)。
## 改动文件
- `deploy/docker-compose.server.yml`
- `deploy/README.md`
- `AGENTS.md`
- `scripts/jyotish_api_server.py`(薄注册;+25 行)
- `scripts/api_heavy_compute_gate.py`(新)
- `scripts/run_quality_gate.py`
- `tests/test_api_server_growth_contract.py`(新)
- `tests/test_api_heavy_compute_gate.py`(新)
- `tests/test_railway_deployment.py`
- `PROGRESS-engine-runtime-hygiene-20260901.md`(本文件)
未改:`deploy/run-staging-deploy.sh``deploy/run-production-deploy.sh``deploy/backup-staging-postgres.sh`
## 明确未做 / blocked
- Staging/production 实机挂卷、重启存活、`/api/health` 部署 SHA(需部署窗口)。
- 完整 quick gate(含 frontend runtime)。
- 迁移 squash。
-`/api/chart` 同步路径送进这道闸。
- 提交 / 推送 / 提升 `main`