[ci skip] f1-stream: add F1 schedule subsystem (Phase 2)
- Fetch 2026 F1 race calendar from jolpica API with all sessions (FP1-3, Qualifying, Sprint, Race) and UTC timestamps - Persist schedule to NFS as JSON, load on startup if fresh - APScheduler daily refresh at 03:00 UTC - GET /schedule endpoint with live/upcoming/past session status - POST /schedule/refresh for manual refresh trigger
This commit is contained in:
parent
f423a4d60c
commit
d7d347de27
6 changed files with 305 additions and 2 deletions
|
|
@ -1,6 +1,54 @@
|
|||
"""F1 Streams - FastAPI backend with schedule service."""
|
||||
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI(title="F1 Streams")
|
||||
from backend.schedule import ScheduleService
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
schedule_service = ScheduleService()
|
||||
scheduler = AsyncIOScheduler()
|
||||
|
||||
|
||||
async def _scheduled_refresh() -> None:
|
||||
"""Callback for APScheduler daily refresh."""
|
||||
logger.info("Running scheduled schedule refresh...")
|
||||
await schedule_service.refresh()
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""Startup and shutdown lifecycle handler."""
|
||||
# Startup: load schedule and start background scheduler
|
||||
await schedule_service.initialize()
|
||||
|
||||
scheduler.add_job(
|
||||
_scheduled_refresh,
|
||||
trigger=CronTrigger(hour=3, minute=0, timezone="UTC"),
|
||||
id="daily_schedule_refresh",
|
||||
name="Refresh F1 schedule daily at 03:00 UTC",
|
||||
replace_existing=True,
|
||||
)
|
||||
scheduler.start()
|
||||
logger.info("APScheduler started - daily refresh at 03:00 UTC")
|
||||
|
||||
yield
|
||||
|
||||
# Shutdown
|
||||
scheduler.shutdown(wait=False)
|
||||
logger.info("APScheduler shut down")
|
||||
|
||||
|
||||
app = FastAPI(title="F1 Streams", lifespan=lifespan)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
|
|
@ -13,6 +61,19 @@ async def root():
|
|||
return {"service": "f1-streams", "version": "2.0.1"}
|
||||
|
||||
|
||||
@app.get("/schedule")
|
||||
async def get_schedule():
|
||||
"""Return the F1 race schedule for the current season with session statuses."""
|
||||
return schedule_service.get_schedule()
|
||||
|
||||
|
||||
@app.post("/schedule/refresh")
|
||||
async def refresh_schedule():
|
||||
"""Manually trigger a schedule refresh from the jolpica API."""
|
||||
await schedule_service.refresh()
|
||||
return {"status": "refreshed"}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue