Compare commits

..

2 Commits

Author SHA1 Message Date
4e322503cc db 2026-03-31 21:54:33 +02:00
e9685193a4 reduce statistics refetch log noise and dedupe requests 2026-03-31 21:54:04 +02:00
2 changed files with 26 additions and 24 deletions

Binary file not shown.

View File

@ -4,6 +4,7 @@ import React, {
useState, useState,
useCallback, useCallback,
useEffect, useEffect,
useRef,
} from "react"; } from "react";
import { useUser, useAuth } from "@clerk/clerk-expo"; import { useUser, useAuth } from "@clerk/clerk-expo";
import { getUserStatistics } from "../api/statistics"; import { getUserStatistics } from "../api/statistics";
@ -36,6 +37,9 @@ export function StatisticsProvider({
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null); const [error, setError] = useState<Error | null>(null);
const [lastFetchTime, setLastFetchTime] = useState<number>(0); const [lastFetchTime, setLastFetchTime] = useState<number>(0);
const statisticsRef = useRef<UserStatisticsResponse | null>(null);
const lastFetchTimeRef = useRef<number>(0);
const fetchInProgressRef = useRef(false);
// Cache statistics for 30 seconds to avoid duplicate calls // Cache statistics for 30 seconds to avoid duplicate calls
const CACHE_DURATION = 30000; // 30 seconds const CACHE_DURATION = 30000; // 30 seconds
@ -43,48 +47,49 @@ export function StatisticsProvider({
const refetchStatistics = useCallback(async () => { const refetchStatistics = useCallback(async () => {
if (!user?.id) return; if (!user?.id) return;
if (fetchInProgressRef.current) {
return;
}
// Check if we have recent cached data // Check if we have recent cached data
const now = Date.now(); const now = Date.now();
if (statistics && now - lastFetchTime < CACHE_DURATION) { if (
log.debug("Using cached statistics", { statisticsRef.current &&
age: now - lastFetchTime, now - lastFetchTimeRef.current < CACHE_DURATION
cacheRemaining: CACHE_DURATION - (now - lastFetchTime), ) {
});
return; return;
} }
try { try {
fetchInProgressRef.current = true;
setLoading(true); setLoading(true);
setError(null); setError(null);
log.debug("Fetching fresh statistics", { userId: user.id });
const token = await getToken(); const token = await getToken();
const stats = await getUserStatistics(user.id, token); const stats = await getUserStatistics(user.id, token);
setStatistics(stats); setStatistics(stats);
statisticsRef.current = stats;
setLastFetchTime(now); setLastFetchTime(now);
log.debug("Statistics fetched and cached", { lastFetchTimeRef.current = now;
userId: user.id,
hasWeeklyTrend: !!stats.weeklyTrend,
weeklyTrendLength: stats.weeklyTrend?.length || 0,
weeklyTrendSample: stats.weeklyTrend?.[0],
stats,
});
} catch (err) { } catch (err) {
const error = err instanceof Error ? err : new Error(String(err)); const error = err instanceof Error ? err : new Error(String(err));
log.error("Failed to fetch statistics", error); log.error("Failed to fetch statistics", error);
setError(error); setError(error);
} finally { } finally {
setLoading(false); setLoading(false);
fetchInProgressRef.current = false;
} }
}, [user?.id, getToken, statistics, lastFetchTime]); }, [user?.id, getToken]);
const clearCache = useCallback(() => { const clearCache = useCallback(() => {
setStatistics(null); setStatistics(null);
statisticsRef.current = null;
setLoading(false); setLoading(false);
setLastFetchTime(0); setLastFetchTime(0);
lastFetchTimeRef.current = 0;
setError(null); setError(null);
log.debug("Statistics cache cleared"); fetchInProgressRef.current = false;
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -100,28 +105,25 @@ export function StatisticsProvider({
if (!user?.id) return; if (!user?.id) return;
try { try {
fetchInProgressRef.current = true;
setLoading(true); setLoading(true);
setError(null); setError(null);
log.debug("Force fetching statistics", { userId: user.id });
const token = await getToken(); const token = await getToken();
const stats = await getUserStatistics(user.id, token); const stats = await getUserStatistics(user.id, token);
setStatistics(stats); setStatistics(stats);
setLastFetchTime(Date.now()); statisticsRef.current = stats;
log.debug("Statistics force fetched and cached", { const now = Date.now();
userId: user.id, setLastFetchTime(now);
hasWeeklyTrend: !!stats.weeklyTrend, lastFetchTimeRef.current = now;
weeklyTrendLength: stats.weeklyTrend?.length || 0,
weeklyTrendSample: stats.weeklyTrend?.[0],
stats,
});
} catch (err) { } catch (err) {
const error = err instanceof Error ? err : new Error(String(err)); const error = err instanceof Error ? err : new Error(String(err));
log.error("Failed to force fetch statistics", error); log.error("Failed to force fetch statistics", error);
setError(error); setError(error);
} finally { } finally {
setLoading(false); setLoading(false);
fetchInProgressRef.current = false;
} }
}, [user?.id, getToken]); }, [user?.id, getToken]);