feat: Host 中间件租户路由(纯ASGI覆盖WS/未知404/停用503暂停页/health豁免)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+9
-10
@@ -6,6 +6,7 @@ from fastapi import FastAPI
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from app.engine.config import STATIC_DIR
|
||||
from app.platform.host_middleware import TenantHostMiddleware
|
||||
from app.platform.registry import TenantRegistry
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -14,9 +15,6 @@ logger = logging.getLogger(__name__)
|
||||
BASE_DIR = Path(__file__).resolve().parents[1]
|
||||
SEED_DIR = BASE_DIR / "seed_profiles"
|
||||
TENANTS_DIR = BASE_DIR / "tenants" # .gitignore 已忽略 tenants/*.db
|
||||
# 过渡兜底(Task 5b→7,中间件上线后随 routes/runtime.py 一并删除):
|
||||
# Host 中间件落地前请求 state 里没有租户,一律落默认租户 jiancai
|
||||
DEFAULT_TENANT_HOST = "chat2.agent.hnxinyouhe.com"
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
@@ -29,15 +27,10 @@ async def lifespan(app: FastAPI):
|
||||
app.state.registry = registry
|
||||
|
||||
try:
|
||||
# 预热默认租户(过渡兜底读 app.state.default_runtime)。engine 建在
|
||||
# 本 lifespan 的事件循环里——连接与 loop 绑定,别处另起 asyncio.run
|
||||
# 复用同一 engine 会跨 loop 死锁(测试直连造数走 conftest.async_db)。
|
||||
# 预热/加载保持 fail-fast:默认租户起不来 = 过渡期全站无租户。
|
||||
app.state.default_runtime = await registry.resolve(DEFAULT_TENANT_HOST)
|
||||
|
||||
# 询盘推送(设计 8.2): 清扫崩溃遗留的 stale pending → failed。逐租户、
|
||||
# 用该租户自己的 session_factory;db 文件不存在的租户跳过——全新库
|
||||
# 无遗留行,保持 engine 懒建纪律(预热的默认租户文件已建,照常扫)。
|
||||
# 无遗留行,保持 engine 懒建纪律(租户 engine 由 Host 中间件按请求
|
||||
# 懒建,启动期只有已有库文件的租户会被扫描)。
|
||||
# 清扫失败只记日志继续:一个租户的坏库不炸整个平台启动(其余租户
|
||||
# 照常服务),该租户下轮重启还会重扫。
|
||||
from app.engine.services.lead_push_service import sweep_stale_pending
|
||||
@@ -80,6 +73,12 @@ async def static_no_cache(request, call_next):
|
||||
return resp
|
||||
|
||||
|
||||
# 租户路由中间件(Task 7): 最后 add = 最外层——租户解析先于一切用户中间件。
|
||||
# 纯 ASGI 类(http+websocket 双覆盖),registry 经 scope["app"] 延迟取,
|
||||
# 因此可在 lifespan 挂 Registry 之前于模块级注册。
|
||||
app.add_middleware(TenantHostMiddleware)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def index():
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
Reference in New Issue
Block a user