Notifications et Push
Vue d’ensemble
Le système de notifications UnikSim combine trois mécanismes complémentaires : une inbox persistée dans Redis, des événements temps réel via Socket.IO, et des push notifications via Firebase Cloud Messaging (FCM). L’objectif est de garantir qu’une notification puisse être visible immédiatement dans l’application lorsque l’utilisateur est connecté, tout en permettant une livraison push lorsque l’application n’est pas active.
1. Architecture générale des notifications
flowchart LR
SRC[Services métier / SupportService] --> NS[NotificationService]
NS --> REDIS[(Redis inbox)]
NS --> EVT[EventEmitter]
NS --> FBS[FirebaseService]
EVT --> GW[SupportGateway]
GW --> ROOM[user_userId]
ROOM --> FE[Frontend Angular / App]
FBS --> TOK[UserFcmToken + subscriptions]
FBS --> FCM[Firebase FCM]
FCM --> DEV[Appareils utilisateur]
FE --> API[API notifications]
API --> REDIS
La persistance Redis et l’envoi FCM sont traités comme deux canaux distincts. Une erreur de push ne supprime donc pas la notification de l’inbox.
2. Création d’une notification pour un utilisateur connecté
sequenceDiagram
participant S as Service métier
participant N as NotificationService
participant R as Redis
participant E as EventEmitter
participant G as SupportGateway
participant F as Frontend
S->>N: notifyUser(userId, type, payload)
N->>N: Construit titre/body localisés
N->>R: LPUSH notification + expiry
R-->>N: Persistée
N->>E: NOTIFICATION_CREATED
E->>G: événement
G-->>F: notification.created
F->>F: upsert dans l'état local
F->>F: incrémente unread + joue le son
Le gateway relaie l’événement dans la room du compte utilisateur. Le frontend peut ainsi mettre à jour l’interface immédiatement sans attendre un prochain GET.
3. Livraison Push via Firebase
sequenceDiagram
participant N as NotificationService
participant FBS as FirebaseService
participant DB as MySQL
participant FCM as Firebase Cloud Messaging
participant D as Appareil
N->>FBS: sendPushNotificationToUser(userId)
FBS->>DB: Charge installations FCM de l'utilisateur
DB-->>FBS: tokens actifs
FBS->>FCM: multicast(tokens, payload)
FCM-->>D: push notification
FCM-->>FBS: résultats par token
FBS->>FBS: détecte invalid/unregistered
FBS->>DB: supprime installations/tokens invalides
Les push sont envoyées à toutes les installations du compte. Pour les notifications liées à un jeu, le backend peut cibler les installations selon leurs subscriptions à des productCodeId.
4. Installations FCM et subscriptions
flowchart TD
APP[Application / appareil] --> REG[registerInstallation]
REG --> OWN[Validation des productCodeIds possédés]
OWN --> CLEAN[Supprime le même token d'anciennes installations]
CLEAN --> UPSERT[Upsert UserFcmToken]
UPSERT --> SUB[Remplace UserFcmSubscriptions]
SUB --> SEND[Envoi futur]
SEND --> MATCH[Filtre ownership + productCodeId]
MATCH --> TOKENS[Liste des tokens]
TOKENS --> FCM[Firebase FCM]
FCM --> BAD{Token invalide ?}
BAD -->|Oui| DEL[Supprime token + subscriptions]
BAD -->|Non| OK[Conserve installation]
5. Cycle de vie d’une notification
stateDiagram-v2
[*] --> CREATED
CREATED --> UNREAD: persistance Redis
UNREAD --> READ: marquer comme lue
READ --> UNREAD: nouvelle notification distincte
UNREAD --> DELETED: supprimer
READ --> DELETED: supprimer
DELETED --> [*]
Architecture frontend
Le frontend maintient une copie locale de l’inbox et fusionne les données provenant de l’API HTTP avec les événements temps réel. Le service principal est user-notification.service.ts.
flowchart LR
API[GET /notifications] --> UNS[UserNotificationService]
SOCK[SupportSocketService] -->|notification.created| UNS
UNS --> STATE[BehaviorSubject notifications]
STATE --> UI[Badge / liste / toast]
UI -->|mark as read| READ[POST /notifications/:uid/read]
UI -->|delete| DEL[DELETE /notifications/:uid]
READ --> UNS
DEL --> UNS
Responsabilités du frontend
- charger l’inbox initiale avec
GET /notifications; - fusionner une notification temps réel avec la liste locale via son UID;
- maintenir un unread count dérivé;
- marquer une notification comme lue;
- supprimer une notification;
- afficher les nouvelles notifications reçues par Socket.IO immédiatement.
Persistance Redis
L’inbox d’un utilisateur est stockée dans une liste Redis dont la clé est dérivée de son identifiant. Les nouvelles notifications sont insérées en tête via LPUSH et la clé reçoit une durée de rétention.
Les opérations read/unread/delete utilisent la liste existante et modifient ou retirent l’entrée concernée.
Notifications liées à un jeu
Le système possède également un chemin de notification lié à un jeu. Avant l’envoi, le backend vérifie que les subscriptions FCM sont toujours cohérentes avec les product codes réellement possédés. Cela évite d’envoyer une notification de jeu à un appareil dont l’accès a été retiré ou réassigné.
Gestion des erreurs
- Une erreur FCM ne doit pas supprimer une notification déjà persistée dans Redis.
- Les tokens invalides ou désenregistrés sont nettoyés après le résultat FCM.
- Les erreurs de persistance, temps réel et push sont journalisées séparément.
- La diffusion temps réel dépend du gateway; l’inbox reste récupérable ensuite via HTTP.
Fichiers principaux
uniksim-back-end/src/service/notification.service.tsuniksim-back-end/src/service/firebase.service.tsuniksim-back-end/src/gateway/support.gateway.tsuniksimFrontEnd/src/app/service/notifications/user-notification.service.tsuniksimFrontEnd/src/app/service/support/support-socket.service.ts
Points d’attention
- La notification doit être persistée avant d’être émise en temps réel.
- L’inbox Redis et le push FCM sont des canaux indépendants.
- Les subscriptions de jeu doivent être validées contre l’ownership courant.
- Les tokens FCM invalides doivent être nettoyés pour éviter des envois inutiles répétés.
- Le frontend doit dédupliquer les notifications temps réel par UID.