feat: 统一入口 dispatcher(对外 opc.pinesound.cn)
- /api/* /uploads/* /SpXvScDiDT.txt → 培训子应用 - 其余 → 平台应用;驱动双子应用 lifespan
This commit is contained in:
@@ -0,0 +1 @@
|
||||
d813c7bbab566807a833fbc3b0e20a9c
|
||||
@@ -0,0 +1,63 @@
|
||||
"""server-core 统一入口(dispatcher)—— 对外生产服务 opc.pinesound.cn 单入口。
|
||||
|
||||
同一端口服务平台应用与培训子应用,按路径路由:
|
||||
/api/*、/uploads/*、/SpXvScDiDT.txt → 培训子应用(app.training,保留 /api 路由与独立 data/opc.db)
|
||||
其余(/auth /opc /admin /agents 等)→ 平台应用(app.main,身份 + 业务域)
|
||||
|
||||
启动(server-core 目录):
|
||||
uv run uvicorn dispatcher:app --host 0.0.0.0 --port 8090 --reload
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from app.main import app as core_app
|
||||
from app.training.main import app as training_app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ROUTE_TRAINING_PREFIXES = ("/api", "/uploads", "/SpXvScDiDT.txt")
|
||||
|
||||
|
||||
class Dispatcher:
|
||||
"""极简 ASGI 分发器:驱动子应用 lifespan(核心库初始化)+ 按路径路由。"""
|
||||
|
||||
def __init__(self, apps: list):
|
||||
self._apps = apps
|
||||
|
||||
async def _run_lifespan(self, receive, send):
|
||||
"""依次进入各子应用 lifespan(核心应用负责建表/种子),按启动/停止消息配对退出。"""
|
||||
started: list = []
|
||||
try:
|
||||
while True:
|
||||
message = await receive()
|
||||
if message["type"] == "lifespan.startup":
|
||||
for a in self._apps:
|
||||
cm = a.router.lifespan_context(app=a)
|
||||
await cm.__aenter__()
|
||||
started.append(cm)
|
||||
await send({"type": "lifespan.startup.complete"})
|
||||
elif message["type"] == "lifespan.shutdown":
|
||||
for cm in reversed(started):
|
||||
await cm.__aexit__(None, None, None)
|
||||
started = []
|
||||
await send({"type": "lifespan.shutdown.complete"})
|
||||
return
|
||||
except BaseException:
|
||||
for cm in reversed(started):
|
||||
try:
|
||||
await cm.__aexit__(None, None, None)
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
raise
|
||||
|
||||
async def __call__(self, scope, receive, send):
|
||||
if scope["type"] == "lifespan":
|
||||
await self._run_lifespan(receive, send)
|
||||
return
|
||||
path = scope.get("path", "")
|
||||
target = training_app if path.startswith(ROUTE_TRAINING_PREFIXES) else core_app
|
||||
await target(scope, receive, send)
|
||||
|
||||
|
||||
app = Dispatcher([core_app, training_app])
|
||||
Reference in New Issue
Block a user