All Stories
3-4-api-request-batching-deduplicationDoneEpic 3.4
Story 3.4: API Request Batching & Deduplication
Status: done
Tasks
- Task 1: Create RequestDeduplicator Class (AC: 1, 2, 6, 9, 10) - ALREADY EXISTS (Story 2-2-1)
- 1.1 `server/app/core/request_coalescer.py` - 352 lines, complete implementation
- 1.2 `_pending: Dict[str, PendingRequest]` tracking with asyncio.Future
- 1.3 `asyncio.Lock` for thread-safe access
- 1.4 `get_or_fetch(key, fetch_fn)` method with coalescing logic
- 1.5 Error propagation via `future.set_exception()`
- 1.6 Timeout via `asyncio.wait_for(future, timeout=max_wait)` (default 5s)
- 1.7 Cleanup in finally block with `del self._pending[cache_key]`
- Task 2: Integrate with Cache Layer (AC: 5) - ALREADY INTEGRATED
- 2.1 `fixtures.py` uses combined cache + coalescing + circuit breaker flow
- 2.2 Order: SWR cache check → coalescer.get_or_fetch() → circuit breaker → API
- 2.3 Cache populated before notifying waiters via SWR pattern
- 2.4 Singleton pattern via `get_request_coalescer()`
- Task 3: Request Batching (AC: 3, 4) - SKIPPED (Deduplication provides most value)
- 3.1-3.5 Optic Odds API does not support batch endpoints
- Request coalescing achieves same goal without API batch support
- Task 4: Metrics Collection (AC: 7, 8) - IMPLEMENTED
- 4.1 `CoalescerStats` dataclass: total_requests, coalesced_requests, api_calls_made
- 4.2 `api_calls_saved` property = coalesced_requests
- 4.3 N/A - using coalescing, not batching
- 4.4 In-memory stats (Redis persistence not needed for monitoring)
- 4.5 Debug logging for coalescing events
- Task 5: Statistics Endpoint (AC: 11) - CREATED
- 5.1 Created `/api/v1/shared/deduplication/stats` endpoint
- 5.2 Returns: coalesced_requests, api_calls_saved, pending_requests, hit_rate_percent
- 5.3 Also added `/api/v1/shared/deduplication/health` and `/stats/reset`
- Task 6: Testing & Validation (AC: 1-11) - 22 TESTS PASSING
- 6.1 Unit tests for RequestCoalescer: test_request_coalescer.py
- 6.2 Load test: test_thundering_herd_prevention (100 concurrent → 1 API call)
- 6.3 Integration test: fixtures.py uses cache + coalescer + circuit breaker
- 6.4 Error propagation: test_error_propagates_to_all_waiters
- 6.5 Timeout: test_max_wait_timeout
- 6.6 Thread safety: concurrent modifications tested
- 6.7 Quota monitoring via stats endpoint
Progress
Tasks6/6
Acceptance Criteria0
Total Tasks6