All Stories
2-1-1-lightweight-game-cards-endpointDoneEpic 2.1
Story 2.1.1: Lightweight Game Cards Endpoint
Status: done
Tasks
- Task 1: Create CardsService (AC: #2, #3, #5)
- 1.1: Create `server/app/services/odds/cards_service.py` with CardsService class
- 1.2: Implement `fetch_game_cards(sport, league, limit, sportsbook)` method
- 1.3: Implement Optic Odds API call with filters: `is_main=true`, `markets=[moneyline,point_spread,total_points]`
- 1.4: Implement `transform_to_cards()` to extract minimal fields from API response
- 1.5: Unit test: verify response shape matches GameCard schema
- Task 2: Create Pydantic Schemas (AC: #2, #3)
- 2.1: Create `server/app/schemas/odds/cards.py` with TeamInfo, FeaturedOdds, GameCard, GameCardsResponse models
- 2.2: Add response size validation (warn if >30KB for 20 games)
- 2.3: Unit test: schema serialization/deserialization
- Task 3: Create API Endpoint (AC: #1, #2)
- 3.1: Create `server/app/api/v1/endpoints/odds/cards.py` router
- 3.2: Implement `GET /api/v1/fixtures/{sport}/cards` endpoint
- 3.3: Add query parameters: `limit` (default: 20, max: 50), `sportsbook` (default: "fanduel"), `league` (optional)
- 3.4: Add input validation with Pydantic
- 3.5: Register router in main app
- 3.6: Integration test: endpoint returns valid GameCardsResponse
- Task 4: Implement Redis Caching with SWR (AC: #4)
- 4.1: Create cache key pattern: `odds:cards:{sport}:{league}` (or `odds:cards:{sport}:all` if no league)
- 4.2: Implement soft TTL (2 min) / hard TTL (5 min) SWR pattern
- 4.3: On cache hit within soft TTL: return cached, no refresh
- 4.4: On cache hit within hard TTL but past soft TTL: return cached, trigger background refresh
- 4.5: On cache miss: fetch from Optic Odds API, cache, return
- 4.6: Add cache hit/miss logging for monitoring
- 4.7: Integration test: verify SWR behavior
- Task 5: Performance Validation (AC: #1, #3)
- 5.1: Add response timing middleware or decorator
- 5.2: Measure and log response time per request
- 5.3: Add response size to meta field in response
- 5.4: Create load test scenario for cards endpoint (extend Locust framework from Story 2.6) - DEFERRED to staging
- 5.5: Validate p95 < 500ms with 20 concurrent requests - DEFERRED to staging
- Task 6: Error Handling & Fallback (AC: #4)
- 6.1: On Optic Odds API failure + cache available: return stale cache with `stale: true` in meta
- 6.2: On Optic Odds API failure + no cache: return 503 with retry guidance
- 6.3: Unit test: verify fallback behavior
Progress
Tasks6/6
Acceptance Criteria0
Total Tasks6