Support temps réel
Vue d’ensemble
Le support utilise HTTP pour valider et persister les conversations, messages et tickets; Socket.IO diffuse les changements après leur sauvegarde. Le refactoring du 30 septembre 2026 sépare le temps réel d’UnikSimdu reposecompte de celui du support. Description vérifiée sur Socket.IO,messagerie_fixes, leHEAD backend3f74bcb0 NestJSet changements indexés; déploiement non vérifié.
Deux namespaces et un modèletransport événementielpartagé
AccountGateway + EventEmitterPresenceServiceSupportGateway SupportService
Frontend
AccountSocketService
SupportSocketService
Événements reçus
user.status, user.presence, admin.status, notification.created
message.created, ticket.updated, typing
Actions émises
updateStatus, updateTelemetry, updateGamePresence
joinConversation, leaveConversation, typing, checkOnline
Les services frontend utilisent RealtimeSocket, qui centralise l’authentification, les observables, la source de persistancereconnexion et les socketsacknowledgements. serventLes ànamespaces diffuserd’un lesmême changementsserveur auxpartagent utilisateursla etconnexion auxsous-jacente, administrateurs.mais leurs rooms sont indépendantes.
1. Architecture temps réel
flowchart LR
U[Utilisateur] --> FE[Frontend Angular / App]
A[Administrateur] --> ADM[Interface admin]
FE <--> WS[SupportGateway - Socket.IO]
ADM <--> WS
FEUI[Interface] --> HTTP[API HTTP NestJS]
ADM --> HTTP
HTTP --> SS[S[SupportService]
SSS --> DB[(MySQL)]
S --> E[EventEmitter]
E --> SG[SupportGateway /support]
SG --> SS[SupportSocketService]
SS --> EVT[EventEmitter]UI
EVTAS[AccountSocketService] <--> AG[AccountGateway /account]
AG --> WSP[PresenceService]
WSN[NotificationService] --> PRES[PresenceService]AG
WSAS --> ROOMS[Rooms Socket.IO]
ROOMS --> UC[user_userId]
ROOMS --> AC[admins]
ROOMS --> CC[conversation_conversationId]
UI
Authentification, rooms et présence
ÀChaque gateway installe socketAuthMiddleware(jwtService) à l’initialisation du namespace. Le JWT est vérifié avant les handlers; le payload est placé dans client.data.user. Le token est accepté depuis handshake.auth.token, la connexion,query ou l’en-tête Authorization.
AccountGateway enregistre et retire les connexions dans PresenceService. Seuls les sockets du namespace compte comptent pour la présence. SupportGateway rejoint user_<id> et, pour les administrateurs, admins; il ne crée pas une seconde connexion de présence.
Pour joinConversation, un utilisateur doit posséder la conversation; les admins peuvent joindre les conversations de support. typing exige l’appartenance à conversation_<id> et ne vise que les autres sockets de cette room. checkOnline interroge PresenceService; un non-admin est limité aux admins assignés à ses tickets.
Message et réponse IA
SupportService valide la conversation et la pièce jointe puis sauvegarde le message USER.
MESSAGE_CREATED est émis; le gateway SupportMapper.toMessageDto et 2. Envoi d’un message utilisateur
sequenceDiagram
actor U as Utilisateur
participant FE as Frontend
participant API as SupportService
participant DB as MySQL
participant EVT as EventEmitter
participant WS as SupportGateway
U->>FE: Envoie un message
FE->>API: POST message
API->>API: Valide conversation et piece jointe
API->>DB: Sauvegarde message USER
DB-->>API: Message cree
API->>EVT: MESSAGE_CREATED
EVT->>WS: evenement
WS-->>FE: message.created vers Lesa messageconversation.
3. Réponse IA dans
Dans une conversation non sequenceDiagramle actorservice Uconstruit asl’historique, Utilisateur
participant SS as SupportService
participant AI as AIService
participant DB as MySQL
participant EVT as EventEmitter
participant WS as SupportGateway
U->>SS: Message utilisateur
SS->>SS: Charge historique +la langue +et retrievalContextsles SS->>AI:droits queryRAG(documentaires puis appelle AIService.queryRAG...) AI-->>SS:La answerréponse /ou insufficient_context
alt answer
SS->>DB: Sauvegardele message AIsystème SS->>EVT:est MESSAGE_CREATEDpersisté EVT->>WS:et evenementdiffusé WS-->>U:par message.createdle elsemême insufficient_contextchemin.
Voir suggestionPipeline d'RAG et système IA pour les clarifications et l’escalade SS->>EVT:lorsque MESSAGE_CREATEDle EVT->>WS:contexte evenementest WS-->>U:insuffisant.
Escalade et cycle de supportvie humaindes end
4. Escalade vers un administrateurtickets
sequenceDiagram
actor U as Utilisateur
participant SS as SupportService
participant DB as MySQL
participant AI as AIService
participant EVT as EventEmitter
participant WS as SupportGateway
actor A as Administrateur
U->>SS: Demande L’escalade SS->>DB:protège Transactionla atomiquetransition conversation.escalatedescalated: false ->→ true
SS->>DB: Cree ticket OPEN
SS->>DB: Sauvegarde message SYSTEM
SS->>EVT: MESSAGE_CREATED + TICKET_UPDATED
EVT->>WS: evenements
WS-->>U: mise a jour conversation
WS-->>A: ticket.updated
SS->>AI: Resume asynchrone de la conversation
AI-->>SS: Resume admin
A->>SS: Assign / repond au ticket
SS->>DB: Sauvegarde ADMIN message + read marker
SS->>EVT: MESSAGE_CREATED + TICKET_UPDATED
EVT->>WS: evenements
WS-->>U: message.created
WS-->>A: ticket.updated
La création du ticket est protégée par une transaction atomiqueatomique. afinElle d’évitercrée plusieursle ticketsticket OPEN, sauvegarde un message SYSTEM, émet MESSAGE_CREATED et TICKET_UPDATED, puis demande un résumé asynchrone pour la même conversation.l’administration. Le premier administrateuradmin qui répond peut automatiquement devenir l’assigné du ticket.assigné.
5. Cycle de vie d’un ticket
stateDiagram-v2
[*] --> OPEN: escaladeOPEN
OPEN --> IN_PROGRESS: assignTicket /ou premierepremière reponseréponse admin
IN_PROGRESSOPEN --> RESOLVED: resolveTicket
OPENIN_PROGRESS --> RESOLVED: resolveTicket
RESOLVED --> IN_PROGRESS: reopenTicket siavec assigneassigné
RESOLVED --> OPEN: reopenTicket sans assigne
assigné
Présence, typingLecture et reconnexion
Le frontend maintient aussi plusieurs signaux temps réel :
Read markers et unread countsnotifications
Les marqueurs delastUserReadAt et lecture/ utilisateurlastUserReadMessageIdadministrateurlastAdminReadAt / lastAdminReadMessageId sont séparés.indépendants. L’utilisateur compte comme non lus les messages ADMIN postérieursnon à son marqueur, alors quelus; l’administrateuradmin compte les messages USER postérieursnon lus. Pour ticket.updated, le gateway obtient deux vues via getTicketUpdates et envoie la vue utilisateur à sonsa propreroom, marqueur.la vue admin à admins.
Les
lastUserReadAtlastUserReadMessageIdlastAdminReadAtlastAdminReadMessageIdFichiers principaux
uniksim-back-end/src/gateway/support.gateway.tsuniksim-back-end/src/service/support.service.tsuniksimFrontEnd/src/app/service/support/support-socket.service.tsPoints d’attention
NotificationService persistance→ doitAccountGateway précéder→ laAccountSocketService. Architecture frontend du support
Le frontend ne traite pas Socket.IO comme une base de données. Les écritures importantes passent par l’API HTTP, puis les événements temps réel mettent l’interfacemises à jour dèsde queticket. leVoir backendNotifications confirmeet le nouvel état.Push.
flowchartReconnexion LR
UI[Composants UI]
API[Services HTTP]
SOCK[SupportSocketService]
STATE[Observables /et état local]
WS[SupportGateway]
BACK[SupportService]
UI -->|actions utilisateur| API
API --> BACK
BACK -->|EventEmitter| WS
WS -->|message.created / ticket.updated / typing / presence| SOCK
SOCK --> STATE
STATE --> UI
UI -->|typing / join / leave / status| SOCK
SOCK --> WS
SupportSocketService
frontend
uniksimFrontEnd/src/app/service/support/support-socket.service.tsSupportSocketServicecentraliseconserve l’ID de conversation active et rejoint sa room à la connexionreconnexion. Socket.IO du frontend. Il expose les principaux événements sous forme de streams/observables afin que les composants n'aient pas à manipuler directement le socket.
message.createdAccountSocketService ticket.updatedtypingnotification.createdReconnexion
Après une reconnexion Socket.IO, le client restaure explicitement son contexte actif :
RealtimeSocket encapsule connect/disconnect, on, emit, emitWithAck et close. L’HTTP charge l’état initial et persiste les actions; les événements synchronisent l’interface.
Fichiers principaux
src/gateway/account.gateway.ts, support.gateway.ts, src/guards/socketAuth.middleware.ts, src/service/presence.service.ts, support.service.ts.
Angular : service/realtime/realtime-socket.ts, service/account/account-socket.service.ts, service/support/support-socket.service.ts et support-state.service.ts.
Contrats : Models/Presence.ts, Models/Notification.ts, Models/Support.ts; constantes : account.constants.ts, realtime.constants.ts, support.constants.ts.
Séparation HTTP / WebSocket
message.createdticket.updated