refactor: Sprint 3 - 引入 UnitOfWork + Repository 架构
新增: - src/db/unit_of_work.py: UnitOfWork 事务封装 - src/db/repositories.py: Match/Team/League/Prediction Repository 重构: - 删除 src/data/match_lookup.py(由 Repository 替代) - 数据源(bzzoiro/understat/injuries)不再自行 commit - API 路由(ingest)改用 UnitOfWork - LLM 服务(predict/orchestrator/eval/backtest)改用 UnitOfWork 事务边界统一由调用方控制,数据层不再自行决定 commit。
This commit is contained in:
+22
-23
@@ -6,7 +6,7 @@ from fastapi import APIRouter, HTTPException
|
||||
from src.api.schemas import IngestBzzoiroRequest, IngestResponse, IngestUnderstatRequest, IngestInjuriesRequest, IngestSimpleResponse
|
||||
from src.data.sources import get_source
|
||||
from src.data.injuries import ingest_injuries
|
||||
from src.db.base import AsyncSessionLocal
|
||||
from src.db.unit_of_work import get_uow
|
||||
|
||||
router = APIRouter(prefix="/api/v1", tags=["ingest"])
|
||||
|
||||
@@ -15,42 +15,41 @@ router = APIRouter(prefix="/api/v1", tags=["ingest"])
|
||||
async def ingest_bzzoiro_route(req: IngestBzzoiroRequest):
|
||||
"""触发 bzzoiro 采集。"""
|
||||
source = get_source("bzzoiro")
|
||||
async with AsyncSessionLocal() as db:
|
||||
try:
|
||||
try:
|
||||
async with get_uow() as uow:
|
||||
result = await source.ingest(
|
||||
db,
|
||||
uow.session,
|
||||
leagues=req.leagues,
|
||||
date_from=req.date_from,
|
||||
date_to=req.date_to,
|
||||
status=req.status,
|
||||
)
|
||||
await db.commit()
|
||||
return IngestResponse(**result)
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
raise HTTPException(500, str(e))
|
||||
await uow.commit()
|
||||
return IngestResponse(**result)
|
||||
except Exception as e:
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@router.post("/ingest/understat", response_model=IngestSimpleResponse)
|
||||
async def ingest_understat_route(req: IngestUnderstatRequest):
|
||||
"""触发 understat xG 回填。"""
|
||||
source = get_source("understat")
|
||||
async with AsyncSessionLocal() as db:
|
||||
try:
|
||||
result = await source.ingest(db, league=req.league, season=req.season)
|
||||
return IngestSimpleResponse(**result)
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
raise HTTPException(500, str(e))
|
||||
try:
|
||||
async with get_uow() as uow:
|
||||
result = await source.ingest(uow.session, league=req.league, season=req.season)
|
||||
await uow.commit()
|
||||
return IngestSimpleResponse(**result)
|
||||
except Exception as e:
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@router.post("/ingest/injuries", response_model=IngestSimpleResponse)
|
||||
async def ingest_injuries_route(req: IngestInjuriesRequest):
|
||||
"""触发伤停采集。"""
|
||||
async with AsyncSessionLocal() as db:
|
||||
try:
|
||||
result = await ingest_injuries(db, date=req.date)
|
||||
return IngestSimpleResponse(**result)
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
raise HTTPException(500, str(e))
|
||||
try:
|
||||
async with get_uow() as uow:
|
||||
result = await ingest_injuries(uow.session, date=req.date)
|
||||
await uow.commit()
|
||||
return IngestSimpleResponse(**result)
|
||||
except Exception as e:
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
Reference in New Issue
Block a user