Add offline clip caching
This commit is contained in:
@@ -3,11 +3,13 @@ from __future__ import annotations
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from fastapi import Request, Response
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ..auth import require_session
|
||||
from ..database import get_db
|
||||
from ..http_cache import build_etag, is_matching_etag, set_private_revalidate
|
||||
from ..models import AudioClip, GameAssignment, UserSession
|
||||
from ..schemas import (
|
||||
GameAssignmentCreate,
|
||||
@@ -37,8 +39,20 @@ def assignment_to_response(assignment: GameAssignment) -> GameAssignmentResponse
|
||||
)
|
||||
|
||||
|
||||
def prepare_conditional_response(
|
||||
request: Request,
|
||||
payload: object,
|
||||
*,
|
||||
exclude_keys: set[str] | None = None,
|
||||
) -> tuple[str, bool]:
|
||||
etag = build_etag(payload, exclude_keys=exclude_keys)
|
||||
return etag, is_matching_etag(request, etag)
|
||||
|
||||
|
||||
@router.get("/pins", response_model=list[GameAssignmentResponse])
|
||||
def list_pins(
|
||||
request: Request,
|
||||
response: Response,
|
||||
external_player_id: str | None = Query(default=None),
|
||||
session: UserSession = Depends(require_session),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -52,11 +66,18 @@ def list_pins(
|
||||
GameAssignment.external_player_id == player_id,
|
||||
)
|
||||
pins = db.scalars(query.order_by(GameAssignment.external_game_id.asc(), AudioClip.sort_order.asc())).all()
|
||||
return [assignment_to_response(assignment) for assignment in pins]
|
||||
payload = [assignment_to_response(assignment) for assignment in pins]
|
||||
etag, not_modified = prepare_conditional_response(request, payload)
|
||||
set_private_revalidate(response, etag=etag)
|
||||
if not_modified:
|
||||
return Response(status_code=304, headers=dict(response.headers))
|
||||
return payload
|
||||
|
||||
|
||||
@router.get("/{external_game_id}/assignments", response_model=list[GameAssignmentResponse])
|
||||
def list_assignments(
|
||||
request: Request,
|
||||
response: Response,
|
||||
external_game_id: str,
|
||||
external_player_id: str | None = Query(default=None),
|
||||
_: UserSession = Depends(require_session),
|
||||
@@ -69,7 +90,12 @@ def list_assignments(
|
||||
if external_player_id:
|
||||
query = query.where(GameAssignment.external_player_id == external_player_id)
|
||||
assignments = db.scalars(query.order_by(AudioClip.sort_order.asc(), GameAssignment.updated_at.desc())).all()
|
||||
return [assignment_to_response(assignment) for assignment in assignments]
|
||||
payload = [assignment_to_response(assignment) for assignment in assignments]
|
||||
etag, not_modified = prepare_conditional_response(request, payload)
|
||||
set_private_revalidate(response, etag=etag)
|
||||
if not_modified:
|
||||
return Response(status_code=304, headers=dict(response.headers))
|
||||
return payload
|
||||
|
||||
|
||||
@router.post("/{external_game_id}/assignments", response_model=GameAssignmentResponse)
|
||||
@@ -136,6 +162,8 @@ def delete_assignment(
|
||||
|
||||
@router.get("/{external_game_id}/prep", response_model=GamePrepResponse)
|
||||
def prepare_game(
|
||||
request: Request,
|
||||
response: Response,
|
||||
external_game_id: str,
|
||||
_: UserSession = Depends(require_session),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -147,9 +175,14 @@ def prepare_game(
|
||||
.order_by(AudioClip.sort_order.asc(), GameAssignment.updated_at.desc())
|
||||
).all()
|
||||
external_team_id = assignments[0].external_team_id if assignments else ""
|
||||
return GamePrepResponse(
|
||||
payload = GamePrepResponse(
|
||||
external_game_id=external_game_id,
|
||||
external_team_id=external_team_id,
|
||||
prepared_at=datetime.now(timezone.utc),
|
||||
assignments=[assignment_to_response(assignment) for assignment in assignments],
|
||||
)
|
||||
etag, not_modified = prepare_conditional_response(request, payload, exclude_keys={"prepared_at"})
|
||||
set_private_revalidate(response, etag=etag)
|
||||
if not_modified:
|
||||
return Response(status_code=304, headers=dict(response.headers))
|
||||
return payload
|
||||
|
||||
Reference in New Issue
Block a user