60 lines
1.7 KiB
Python
60 lines
1.7 KiB
Python
import asyncio
|
||
import threading
|
||
from contextlib import asynccontextmanager
|
||
|
||
from fastapi import FastAPI
|
||
from fastapi.middleware.cors import CORSMiddleware
|
||
from app.routers import analytics, papers, attempts, questions
|
||
|
||
|
||
def _resume_stale_papers():
|
||
"""启动时检查卡在 processing 的 paper,自动续传 AI trio"""
|
||
try:
|
||
from app.services.supabase_client import get_supabase
|
||
from app.services.paper_processor import process_paper
|
||
|
||
sb = get_supabase()
|
||
stale = sb.table("papers").select("id").eq("status", "processing").execute().data
|
||
if not stale:
|
||
return
|
||
|
||
for p in stale:
|
||
paper_id = p["id"]
|
||
print(f"[STARTUP] Resuming processing for paper {paper_id[:8]}...")
|
||
|
||
def run(pid=paper_id):
|
||
asyncio.run(process_paper(pid, b"", None))
|
||
|
||
threading.Thread(target=run, daemon=True).start()
|
||
except Exception as e:
|
||
print(f"[STARTUP] Resume skipped: {e}")
|
||
|
||
|
||
@asynccontextmanager
|
||
async def lifespan(app: FastAPI):
|
||
# Startup
|
||
_resume_stale_papers()
|
||
yield
|
||
# Shutdown (nothing to do)
|
||
|
||
|
||
app = FastAPI(title="PastPaper Master API", version="0.1.0", lifespan=lifespan)
|
||
|
||
app.add_middleware(
|
||
CORSMiddleware,
|
||
allow_origins=["*"], # 开发阶段先放开,上线收紧
|
||
allow_credentials=True,
|
||
allow_methods=["*"],
|
||
allow_headers=["*"],
|
||
)
|
||
|
||
app.include_router(papers.router, prefix="/api/papers", tags=["papers"])
|
||
app.include_router(attempts.router, prefix="/api/attempts", tags=["attempts"])
|
||
app.include_router(questions.router, prefix="/api/questions", tags=["questions"])
|
||
app.include_router(analytics.router, prefix="/api/analytics", tags=["analytics"])
|
||
|
||
|
||
@app.get("/health")
|
||
def health():
|
||
return {"status": "ok"}
|