d041077bb6
- main.py: 删全局 engine/async_session;lifespan 装配 TenantRegistry (seed_profiles → 仓库根 tenants/,路径锚定),预热默认租户 jiancai 挂 app.state.default_runtime,逐 active 租户(库文件已存在)跑 sweep_stale_pending,退出 dispose_all。app.state.registry 预置即沿用 (测试注入缝) - routes/runtime.py(过渡,Task 7 删): get_runtime——state.tenant 优先, 缺省落 default_runtime;chat.py/chat_rest.py 全部改走它,消除 main↔routes 循环依赖 - ConversationManager 构造线: 新增 runtime 可选参(持 session_factory/ compiled_wall/config 引用;prompts 仍模块级,Task 6;业务接线 Task 9), fire_pending_pushes 随任务传 session_factory(后台写回派发租户的库) - lead_push_service: 去 app.main import;写库入口显式收 session_factory, 模块级 async_session=None 仅作测试注入兜底 - conftest: client 夹具 = 每测试独立 Registry(tmp data_dir)+ 真实 lifespan 在 TestClient 循环内预热;删 _dispose_main_engine; async_db 保持 NullPool(跨 asyncio.run 循环安全,刻意不换 Registry 引擎) - 测试仅动夹具/桩签名(断言零改动): wiring 桩补 session_factory 形参; history-404 用例改经真实 WS 路由造 widget 会话(引擎常驻连接绑定 TestClient 循环,测试线程不得直开 session_factory) Co-Authored-By: Claude Code <noreply@anthropic.com>
27 lines
1.2 KiB
Python
27 lines
1.2 KiB
Python
"""路由取当前租户运行时——Task 5b→7 的过渡兜底。
|
|
|
|
Task 7 的 Host 中间件上线前,没有人为请求挂 ``state.tenant``。本助手的
|
|
兜底规则 = state 里有租户用 state 的(中间件灰度接入即生效);没有则用
|
|
``app.state.default_runtime``(lifespan 预热的默认租户 jiancai),API 测试
|
|
与直连(无 Host 语义)在 5b→7 过渡期不断。
|
|
|
|
已知过渡限制(记录在案,Task 7 一并解决):默认租户经 registry_reload
|
|
热切换后 default_runtime 仍指向旧 runtime——过渡期不修,Task 7 中间件
|
|
按请求 Host 重新 resolve 后本模块整体删除。
|
|
"""
|
|
from fastapi import Request, WebSocket
|
|
|
|
from app.platform.registry import 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:
|
|
return runtime
|
|
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")
|
|
return runtime
|