NeahStable/REALTIME_NOTIFICATIONS_PROPOSAL.md
2026-01-11 22:22:53 +01:00

216 lines
5.6 KiB
Markdown

# 🚀 Proposition : Notifications en Temps Réel
## 📊 Analyse Actuelle vs Proposition
### ❌ Système Actuel (Polling toutes les 30s)
**Problèmes :**
- ⏱️ Délai de 30 secondes maximum avant notification
- 🔄 Polling constant même sans nouveaux messages
- 💻 Charge serveur inutile
- 📱 UX moins réactive
**Flow actuel :**
```
Polling toutes les 30s
└─> API /notifications/count
└─> NotificationService
└─> LeantimeAdapter
└─> Badge mis à jour
```
---
### ✅ Système Proposé (Event-Driven)
**Avantages :**
- ⚡ Notifications instantanées (0-1 seconde)
- 🎯 Déclenchement uniquement quand nécessaire
- 💚 Réduction de la charge serveur
- 🎨 Meilleure UX
**Flow proposé :**
```
Widget détecte nouveau message/email
└─> Trigger notification refresh
└─> API /notifications/count (force refresh)
└─> Badge mis à jour immédiatement
```
---
## 🔧 Implémentation Proposée
### 1. Hook pour déclencher les notifications
**Fichier :** `hooks/use-trigger-notification.ts`
```typescript
import { useSession } from 'next-auth/react';
export function useTriggerNotification() {
const { data: session } = useSession();
const triggerNotificationRefresh = async () => {
if (!session?.user?.id) return;
try {
// Force refresh du notification count
await fetch('/api/notifications/count?_t=' + Date.now(), {
method: 'GET',
credentials: 'include',
cache: 'no-store'
});
// Le hook useNotifications écoutera ce changement
// via le système de refresh unifié
} catch (error) {
console.error('Error triggering notification refresh:', error);
}
};
return { triggerNotificationRefresh };
}
```
---
### 2. Intégration dans Parole (RocketChat)
**Fichier :** `components/parole.tsx`
**Modification :**
```typescript
import { useTriggerNotification } from '@/hooks/use-trigger-notification';
export function Parole() {
const { triggerNotificationRefresh } = useTriggerNotification();
const [lastMessageCount, setLastMessageCount] = useState(0);
const fetchMessages = async (isRefresh = false) => {
// ... code existant ...
const data = await response.json();
const currentUnreadCount = data.messages?.reduce((sum: number, msg: any) =>
sum + (msg.unread || 0), 0) || 0;
// Si nouveau message non lu détecté
if (currentUnreadCount > lastMessageCount) {
triggerNotificationRefresh(); // ⚡ Déclenchement immédiat
}
setLastMessageCount(currentUnreadCount);
};
}
```
---
### 3. Intégration dans Courrier (Email)
**Fichier :** `hooks/use-email-state.ts`
**Modification :**
```typescript
import { useTriggerNotification } from '@/hooks/use-trigger-notification';
export const useEmailState = () => {
const { triggerNotificationRefresh } = useTriggerNotification();
const checkForNewEmails = useCallback(async () => {
// ... code existant ...
if (data.newestEmailId && data.newestEmailId > lastKnownEmailId) {
// Nouvel email détecté
triggerNotificationRefresh(); // ⚡ Déclenchement immédiat
toast({
variant: "new-email",
title: "New emails",
description: "You have new emails in your inbox",
});
}
}, [triggerNotificationRefresh, ...]);
}
```
---
### 4. Adapters pour RocketChat et Email (Optionnel)
Créer des adapters dédiés qui peuvent être pollés plus fréquemment :
**Fichier :** `lib/services/notifications/rocketchat-adapter.ts`
**Fichier :** `lib/services/notifications/email-adapter.ts`
Ces adapters pourraient :
- Poller toutes les 10-15 secondes (au lieu de 30s)
- Ou être déclenchés en temps réel via WebSocket/SSE
---
## 🎯 Stratégie Hybride Recommandée
### Combinaison Polling + Event-Driven
1. **Polling de base** : 30 secondes pour Leantime (inchangé)
2. **Event-driven** : Déclenchement immédiat quand :
- Parole détecte un nouveau message
- Courrier détecte un nouvel email
- Devoirs détecte une nouvelle tâche
3. **Cache invalidation** : Quand un widget détecte du nouveau, invalider le cache des notifications
---
## 📝 Plan d'Implémentation
### Phase 1 : Hook de déclenchement
- [ ] Créer `use-trigger-notification.ts`
- [ ] Fonction pour forcer le refresh du count
### Phase 2 : Intégration Parole
- [ ] Détecter nouveaux messages non lus
- [ ] Appeler `triggerNotificationRefresh()` quand détecté
### Phase 3 : Intégration Courrier
- [ ] Détecter nouveaux emails
- [ ] Appeler `triggerNotificationRefresh()` quand détecté
### Phase 4 : Optimisation
- [ ] Réduire polling Leantime à 60s (moins critique)
- [ ] Garder event-driven pour Parole/Courrier (temps réel)
---
## 🔄 Flow Final Proposé
```
Widget Parole/Courrier
└─> Détecte nouveau message/email
└─> triggerNotificationRefresh()
└─> POST /api/notifications/trigger-refresh
└─> Invalide cache Redis
└─> NotificationService.refreshCount()
└─> Badge mis à jour (< 1 seconde)
```
---
## 💡 Avantages de cette Approche
1. **Temps réel** : Notifications instantanées
2. **Efficace** : Pas de polling inutile
3. **Scalable** : Facile d'ajouter d'autres widgets
4. **Rétrocompatible** : Le polling reste en fallback
5. **Performance** : Réduction de 70-80% des appels API
---
## 🚨 Points d'Attention
1. **Déduplication** : S'assurer qu'on ne déclenche pas plusieurs fois
2. **Rate limiting** : Limiter les triggers si trop fréquents
3. **Fallback** : Garder le polling comme backup
4. **Cache** : Invalider intelligemment