diff --git a/web/app.py b/web/app.py index bbd732b..ab98481 100644 --- a/web/app.py +++ b/web/app.py @@ -5,12 +5,14 @@ `api_prefix` 用于把整套路由挂到指定前缀下(便于契约测试与反向代理)。 """ +import asyncio from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI from fastapi.staticfiles import StaticFiles +import auth_system from core.config import APP_VERSION from core.security import init_secret_key from web.errors import install_error_handlers @@ -35,7 +37,16 @@ from web.routers import user as user_router @asynccontextmanager async def _lifespan(app: FastAPI): - """应用生命周期:关闭时释放 aiohttp 连接池(含按事件循环隔离的 session)。""" + """应用生命周期:启动确保站点库表结构就绪,关闭时释放 aiohttp 连接池。 + + 启动必须建表。全新部署时宿主机的 data/ 往往是个空目录(compose 用 + `./data:/app/data` 挂载,会盖掉镜像内的任何内容),此时若只等首次查询 + 让 sqlite3 自动建库,得到的是一张 **0 表空库**——随后所有涉库端点报 + `no such table: users`(实测登录端点直接 500,且错误被吞成"请稍后重试", + 极难定位)。init_db 全程 `CREATE TABLE IF NOT EXISTS` + 幂等迁移, + 对已有库重复执行无副作用,故放启动期最稳妥。 + """ + await asyncio.to_thread(auth_system.init_db) yield try: from core import aiohttp_compat, http_client