Skip to main content

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é

basé
sur Responsabilité Compte : /account Support : /support Backend AccountGateway + EventEmitterPresenceService. HTTPSupportGateway reste+ 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

    L’interface envoie le message et la pièce jointe par HTTP. SupportService valide la conversation et la pièce jointe puis sauvegarde le message USER. MESSAGE_CREATED est émis; le gateway authentifiemappe le JWT,message attacheavec l’utilisateur au socketSupportMapper.toMessageDto et enregistrediffuse son état de présence. Les conversations utilisent des rooms dédiées, tandis que les événements destinés au compte ou aux administrateurs sont envoyés dans leurs rooms respectives.

    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.

    est d’abord persisté, puis diffusé. Le socket ne remplace donc pas la persistance HTTP : il propage simplement le nouvel état.

    3. Réponse IA dans

    Dans une conversation non escaladéeescaladée,
    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.
    SS->>DB: Sauvegarde

    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.

    Proposition

    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 :

      typing : diffusé uniquement aux autres sockets de la conversation active. online / away : dérivé de l’activité navigateur, du focus et d’un timer d’inactivité. telemetry : navigateur, plateforme, résolution, langue, seulement si le consentement est accordé. game presence : jeu actif, productCode et heure de démarrage. reconnect : le client renvoie présence, télémétrie, conversation active et présence de jeu.

      Read markers et unread countsnotifications

      Les marqueurs delastUserReadAt lecture/ utilisateurlastUserReadMessageId et administrateurlastAdminReadAt / 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

        lastUserReadAt / lastUserReadMessageId lastAdminReadAt / lastAdminReadMessageId

        Fichiers principaux

          uniksim-back-end/src/gateway/support.gateway.ts uniksim-back-end/src/service/support.service.ts uniksimFrontEnd/src/app/service/support/support-socket.service.ts

          Points d’attention

            Ne pas utiliser Socket.IO comme sourcenotifications de véritécompte :suivent laNotificationService persistance→ doitAccountGateway précéder→ laAccountSocketService. diffusion.Elles Vérifiersont l’appartenance à une conversation avant de joindre sa room. Les non-admins ne doivent pouvoir vérifier que la présencedistinctes des administrateurs qui leur sont assignés. Après reconnexion, le client doit restaurer ses rooms et états actifs.

            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.

            flowchart

            Reconnexion 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.tsSupportSocketService centraliseconserve 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 :remet ajoute ou rafraîchit un message dans la conversation. ticket.updated : rafraîchit l'état du ticket et ses unread counts. typing : affiche l'indicateur de saisie. présence utilisateur/admin : met à jour les états online/away. notification.created : propage une nouvelle notification et déclenche le son associé.

              Reconnexion

              Après une reconnexion Socket.IO, le client restaure explicitement son contexte actif :

                repasse l'l’utilisateur en ligne;ligne, renvoieréémet la télémétrie si le consentement est toujoursaccordé autorisé;et rejointrestaure à nouveau la conversation active; renvoie la présence dule jeu actif. Le retrait du consentement envoie une télémétrie nulle; quitter le jeu efface sa présence. Les composants support restent centrés sur les messages, tickets et leur état local.

                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

                  Backend : 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

                  HTTP WebSocket Créer/envoyer un message Recevoir message.created Assigner/résoudre/réouvrir un ticket Recevoir ticket.updated Marquer comme lu Présence, typing et changements temps réel Persistance et validation Synchronisation immédiate de l'interface