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

5.6 KiB

🚀 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

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 :

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 :

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