Race Conditions - Correction du Dashboard Étudiant
Date : 23 février 2026 Auteur : GNIMAGNON Arès Statut : Corrigé
Problème
Sur la page /student/search (et potentiellement d'autres pages du dashboard étudiant), l'affichage des données était incohérent :
- Parfois affichait 0 offre
- Parfois affichait le bon nombre d'offres avec les détails
Cause racine
Race condition dans le flux de chargement des données :
- Cache backend TTL trop long (5 minutes) - Données pouvant être obsolètes
- Plusieurs requêtes HTTP concurrentes sans annulation :
- Requête A : avec filtres initiaux (vides)
- Requête B : avec filtres du profil étudiant
- Celle qui arrive en dernier écrase l'état
data
Solution implémentée
1. AbortController (Frontend)
Tous les hooks concernés ont été modifiés pour utiliser AbortController afin d'annuler les requêtes précédentes :
const abortControllerRef = useRef<AbortController | null>(null);
const fetchData = useCallback(async (signal?: AbortSignal) => {
// Annuler toute requête en cours
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
// Créer un nouveau contrôleur
const controller = new AbortController();
abortControllerRef.current = controller;
// Utiliser le signal pour l'API
const result = await apiCall(controller.signal);
}, []);
// Nettoyage dans useEffect
useEffect(() => {
const controller = new AbortController();
fetchData(controller.signal);
return () => controller.abort();
}, [fetchData]);
2. Réduction du TTL du cache (Backend)
Le TTL du cache Redis pour les offres publiques a été réduit :
| Avant | Après |
|---|---|
| 300s (5 min) | 60s (1 min) |
Fichier : backend/app/api/v1/routers/themes.py
Hooks corrigés
Priorité HAUTE (corrigés)
| Hook | Fichier | Problème |
|---|---|---|
useStudentSearch | hooks/student/useStudentSearch.ts | Requêtes concurrentes avec filtres |
useStudentProfile | hooks/student/useStudentProfile.ts | Pas d'annulation + background refresh |
useStudentDocuments | hooks/student/useStudentDocuments.ts | Promise.all parallèle sans annulation |
Priorité MOYENNE (corrigés)
| Hook | Fichier | Problème |
|---|---|---|
useStudentQualifications | hooks/student/useStudentQualifications.ts | Pas de cancellation → ✅ Corrigé |
useStudentApplications | hooks/student/useStudentApplications.ts | Flag cancelled faible → ✅ Corrigé |
Priorité MOYENNE (corrigés)
| Hook | Fichier | Problème |
|---|---|---|
useStudentDashboard | hooks/student/useStudentDashboard.ts | Flag cancelled faible → ✅ Corrigé |
useInternshipDetails | hooks/student/useInternshipDetails.ts | Flag mounted faible → ✅ Corrigé |
useBinomeManagement | hooks/student/useBinomeManagement.ts | Pas de cancellation → ✅ Corrigé |
Hooks OK (pas de correction needed)
useCurrentInternship- Utilise React QueryuseBinome- Utilise React Query
Fichiers modifiés
Backend
backend/app/api/v1/routers/themes.py- TTL cache réduit
Frontend - Services
stage-connect/services/student.search.services.ts- Support AbortSignalstage-connect/services/student.profile.services.ts- Support AbortSignalstage-connect/services/student.documents.services.ts- Support AbortSignalstage-connect/services/student.qualifications.services.ts- Support AbortSignalstage-connect/services/student.applications.services.ts- Support AbortSignalstage-connect/services/student.dashboard.services.ts- Support AbortSignalstage-connect/services/student.pairs.services.ts- Support AbortSignal
Frontend - Hooks
stage-connect/hooks/student/useStudentSearch.ts- AbortControllerstage-connect/hooks/student/useStudentProfile.ts- AbortControllerstage-connect/hooks/student/useStudentDocuments.ts- AbortControllerstage-connect/hooks/student/useStudentQualifications.ts- AbortControllerstage-connect/hooks/student/useStudentApplications.ts- AbortControllerstage-connect/hooks/student/useStudentDashboard.ts- AbortControllerstage-connect/hooks/student/useInternshipDetails.ts- AbortControllerstage-connect/hooks/student/useBinomeManagement.ts- AbortController
Comment tester
- Ouvrir
/student/searchplusieurs fois - Vérifier que le nombre d'offres est cohérent
- Vérifier que les filtres du profil sont bien appliqués
- Tester avec différents profils étudiants
- Tester
/student/profileet/student/documents
Bonnes pratiques pour les nouveaux hooks
Lors de la création d'un nouveau hook qui fetch des données :
- Toujours utiliser AbortController pour annuler les requêtes
- Gérer les AbortError dans le catch
- Nettoyer dans le useEffect (return avec abort)
- Réduire le cache backend si les données changent fréquemment
useEffect(() => {
const controller = new AbortController();
loadData(controller.signal);
return () => controller.abort();
}, [loadData]);