feat: implement request deduplication in useFetchData

- Add optional requestKey parameter to UseFetchDataOptions
- Implement module-level cache (inFlightRequests) to track in-flight requests
- When requestKey is provided, multiple hook instances with same key share in-flight requests
- Prevents duplicate API calls when multiple components fetch same data or rapid refresh calls
- Cache entries are automatically cleared when response arrives (success or error)
- Maintains backward compatibility: without requestKey, behaves as before
- Adds comprehensive tests for deduplication scenarios

This reduces bandwidth waste and prevents race conditions caused by concurrent requests for identical data.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-05-01 18:44:46 +02:00
parent e46062d4cd
commit 3b3728c58d
3 changed files with 248 additions and 66 deletions

View File

@@ -1,62 +1,3 @@
## [MEDIUM] No Application Performance Monitoring (APM)
**Status: COMPLETED ✓**
**What was done:**
- Backend Prometheus metrics: `/metrics` endpoint exposes request count, latency, active requests
- Frontend web-vitals tracking: FCP, LCP, CLS, INP, TTFB collection
- API call metrics: automatic tracking of latency and error rates
- Complete documentation with examples and integration guides
**Implementation:**
- Backend: `app/utils/metrics.py`, `app/middleware/metrics.py`, `app/routers/metrics.py`
- Frontend: `src/utils/metrics.ts`, `src/hooks/useTrackedFetch.ts`
- Documentation: `Docs/Observability.md` (APM section)
**Metrics exposed:**
- `bangui_http_requests_total` - HTTP request count by method, endpoint, status
- `bangui_http_request_duration_seconds` - Request latency histogram
- `bangui_http_active_requests` - Current active requests gauge
- Web Vitals: CLS, FCP, INP, LCP, TTFB
- API call metrics: method, endpoint, status, duration
---
## [LOW] Frontend charts not memoized
**Where found**
- `frontend/src/components/TopCountriesPieChart.tsx`
- `frontend/src/components/TopCountriesBarChart.tsx`
**Why this is needed**
Charts re-render on every parent update, Recharts reprocesses 5000+ points.
**Goal**
Memoize chart components.
**What to do**
1. Wrap with `React.memo` with custom comparison
2. Ensure data objects are stable
**Possible traps and issues**
- Shallow comparison might not be enough
- Memoization has memory cost
**Docs changes needed**
- No documentation changes
**Doc references**
- `frontend/src/components/TopCountriesChart.tsx`
---
## [LOW] No request deduplication on frontend
**Where found**