chore(ops): reload 卡死三层预防 + F1-5a 完整走查报告
reload 卡死三层预防(走查中遭遇 uvicorn graceful shutdown 死等触发): - Layer 1 (apps/backend/start_uvicorn.py 新): 把 reload-excludes 封装在 Python 字符串内,ps1 命令行只有字面路径,根治 PowerShell PSNativeCommandArgumentPassing 在不同 profile 下 wildcard 展开 行为差异(数组 splatting 和 --% 都不稳)。同时显式设 timeout-graceful-shutdown=5,5 秒强杀防死等 - Layer 2 (scripts/ops/backend-watchdog.ps1 新): 自主 socket 探针 (TcpClient + 手写 HTTP/1.1 GET,Connection: close)规避 .NET HttpClient pool 复用 + 系统代理误报;3s × 3 = 9s 触发重启; 进程链 kill 至 pwsh 后端窗口(关闭原窗口);3 次/小时上限自停 - Layer 3 (scripts/ops/start-admin.ps1): 启动时拉起 watchdog, 菜单 [4] 仅重启后端选项,主菜单退出时一并 kill 看门狗 CLAUDE.md: 新增"后端 reload 卡死预防(强制)"章节, 分级文件风险表 + SOP + 启动菜单速查 走查报告(应查尽查严肃版): - 后端 6 个改造点 PASS(P1-P4 + GUC + ai_run_logs runtime 字段) - admin-web 7 页 Playwright 实地走查 → 5 项 UI 不完整登记 F1-5b - 小程序看板 tab 7 页 weixin-devtools-mcp 实地 + DB 数据核对 → board-finance 5/6 项上界裁剪吻合;board-customer 业务日生效; board-coach 月度聚合表设计盲区;5 项 sandbox 覆盖盲区登记 F1-5b - 8 张走查截图归档 docs/audit/changes/screenshots/2026-05-05_f1_5a_walkthrough/ audit_dashboard 刷新到 153 条审计 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
44
apps/backend/start_uvicorn.py
Normal file
44
apps/backend/start_uvicorn.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""后端 uvicorn 启动入口(规避 PowerShell wildcard 展开问题)。
|
||||
|
||||
CHANGE 2026-05-05 | F1-5a 走查发现:PS 7.6.1 即使用 --% stop-parsing token
|
||||
仍在某些环境下展开 reload-exclude 的 wildcard,导致 click 报 "extra arguments"。
|
||||
解决:把所有 wildcard 字符串封装在 Python 内部,ps1 只调本脚本,
|
||||
PowerShell shell 不接触任何 wildcard 字符串。
|
||||
|
||||
参数解析:--port N(默认 8000),其他参数硬编码。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import uvicorn
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--port", type=int, default=8000)
|
||||
parser.add_argument("--host", type=str, default="127.0.0.1")
|
||||
args = parser.parse_args()
|
||||
|
||||
uvicorn.run(
|
||||
"app.main:app",
|
||||
host=args.host,
|
||||
port=args.port,
|
||||
reload=True,
|
||||
# 业务规则:5 秒 graceful shutdown 失败强杀,避免 reload 卡死
|
||||
timeout_graceful_shutdown=5,
|
||||
# F1-5a 走查 reload 卡死预防:
|
||||
# tests/__pycache__/.md 改动不应触发 reload(浪费且潜在卡死风险)
|
||||
reload_excludes=[
|
||||
"tests/*",
|
||||
"**/__pycache__/*",
|
||||
"*.md",
|
||||
],
|
||||
use_colors=False,
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user