fix: 装配切换审查修复(启动异常路径韧性/清扫隔离/文案与夹具卫生)
- main.lifespan: 预热+清扫挪进 try,finally dispose_all 覆盖启动半途 失败(幂等于更少引擎,堵 engine 泄漏);清扫循环体 per-tenant try/except + logger.exception 后继续——一个租户坏库不炸平台启动, resolve/load_from_dir 保持 fail-fast - routes/runtime.py: RuntimeError 文案补 registry_reload dispose 旧 runtime 成因;TenantRuntime 注解挪 TYPE_CHECKING(engine 包运行期 零 import platform) - conftest client: teardown 置空 app.state.registry(关残留窗); rmtree 先正常删,失败 warnings.warn 留痕后再 ignore_errors 兜底 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -9,12 +9,17 @@ Task 7 的 Host 中间件上线前,没有人为请求挂 ``state.tenant``。本
|
||||
热切换后 default_runtime 仍指向旧 runtime——过渡期不修,Task 7 中间件
|
||||
按请求 Host 重新 resolve 后本模块整体删除。
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from fastapi import Request, WebSocket
|
||||
|
||||
from app.platform.registry import TenantRuntime
|
||||
if TYPE_CHECKING:
|
||||
# 仅类型注解用: engine 包运行期零 import platform(依赖方向保持
|
||||
# platform → engine,反向只在类型层)
|
||||
from app.platform.registry import TenantRuntime
|
||||
|
||||
|
||||
def get_runtime(request_or_ws: Request | WebSocket) -> TenantRuntime:
|
||||
def get_runtime(request_or_ws: Request | WebSocket) -> "TenantRuntime":
|
||||
"""state.tenant 优先,缺省落 app.state.default_runtime(Task 7 删)。"""
|
||||
runtime = getattr(request_or_ws.state, "tenant", None)
|
||||
if runtime is not None:
|
||||
@@ -22,5 +27,6 @@ def get_runtime(request_or_ws: Request | WebSocket) -> TenantRuntime:
|
||||
runtime = getattr(request_or_ws.app.state, "default_runtime", None)
|
||||
if runtime is None or runtime.session_factory is None:
|
||||
raise RuntimeError(
|
||||
"默认租户运行时未就绪——lifespan 未运行或未预热 default_runtime")
|
||||
"默认租户运行时未就绪——lifespan 未运行、未预热 default_runtime,"
|
||||
"或 registry_reload 已 dispose 旧 runtime(过渡期限制,Task 7 解决)")
|
||||
return runtime
|
||||
|
||||
Reference in New Issue
Block a user