Retour à l'accueil

Notifications SSE dans SPA : temps réel sans polling

L'article décrit l'architecture des notifications asynchrones dans SPA basée sur SSE et Mercure. Intégration avec CDC pour le suivi des changements de DB, réutilisation des schémas OpenAPI pour le typage. Exemples de code et diagrammes pour les développeurs.

Notifications push SSE dans SPA : architecture et code
Advertisement 728x90

Mises à jour asynchrones de données dans les SPA avec SSE et Mercure

Les applications frontend nécessitent des mises à jour constantes des données pour refléter les changements du backend. Les appels API standards capturent l'état au moment de la réponse, mais le backend continue de traiter des événements : rechargements de compte, modération de contenu, réponses au support. Pour y remédier, des mécanismes de push basés sur SSE sont utilisés, intégrés à la spécification OpenAPI existante.

Le système combine une approche pull (requêtes périodiques) avec du push (notifications en temps réel). SSE fournit un flux d'événements unidirectionnel sur HTTP/2, minimisant la charge par rapport au polling.

Cas d'utilisation des notifications asynchrones

Les notifications asynchrones sont cruciales dans les processus métier :

Google AdInline article slot
  • Rechargement de solde : Affichage de l'état actuel pour des achats immédiats.
  • Modération de contenu : Mise à jour du statut après examen.
  • Réponses au support : Notification instantanée d'un nouveau ticket.

Dans un cas typique, l'utilisateur—un annonceur ou un prestataire—suit des compteurs de requêtes : le nombre nécessitant une action, les commentaires non lus, les vérifications de placement. Ces données sont disponibles via le point de terminaison API /rest/User/info (operationId : getInfo).

/rest/User/info:
  get:
    tags:
      - Utilisateur
    summary: Retourne des informations sur l'utilisateur actuel
    operationId: getInfo
    responses:
      200:
        description: Informations sur l'utilisateur actuel
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                  format: int32
                  minimum: 0
                locale:
                  type: string
                  enum: [ru, en]
                login:
                  type: string
                  minimum: 3
                  maximum: 320
                seoCounters:
                  $ref: '#/components/schemas/SeoCounters'

Le schéma SeoCounters définit la structure :

SeoCounters:
  type: object
  properties:
    nofRequests:
      type: integer
      format: int32
      minimum: 0
    nofLinksStatusNeedApprove:
      type: integer
      format: int32
      minimum: 0
    nofLinksWithUnreadComments:
      type: integer
      format: int32
      minimum: 0
    nofChanges:
      type: integer
      format: int32
      minimum: 0
    nofPlacementCheck:
      type: integer
      format: int32
      minimum: 0

Intégration de CDC et Data Platform

Les changements dans la table user_counters sont suivis via CDC (Change Data Capture). Le flux de modifications est envoyé à la Data Platform—un système ETL d'entreprise. De là, les événements sont poussés vers l'interface utilisateur via un hub SSE.

Google AdInline article slot

L'architecture utilise un modèle hexagonal : la spécification OpenAPI génère automatiquement des adaptateurs REST et des types TypeScript. Pour le frontend, les types ressemblent à ceci :

/* Généré par orval */
export interface SeoCounters {
  nofRequests?: number;
  nofLinksStatusNeedApprove?: number;
  nofLinksWithUnreadComments?: number;
  nofChanges?: number;
  nofPlacementCheck?: number;
}

export type GetInfo200 = {
  id: number;
  locale: 'ru' | 'en';
  login: string;
  seoCounters?: SeoCounters;
};

Ces types sont réutilisés pour traiter les événements SSE, garantissant la sécurité des types.

Mise en œuvre de SSE dans l'application

SSE (Server-Sent Events) est une norme pour les push serveur, prise en charge par les navigateurs. EventSource se connecte au point de terminaison :

Google AdInline article slot
const evtSource = new EventSource('/sse-endpoint', {
  withCredentials: true,
});

evtSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  // Mettre à jour le store avec des données typées
  updateSeoCounters(data.seoCounters);
};

Pour l'autorisation, les sujets et la mise à l'échelle, Mercure est utilisé—un hub open-source basé sur SSE. Le hub accepte les publications via REST avec JWT et diffuse aux abonnés.

Exemple de publication :

curl -d 'topic=https://example.com/books/1' \
     -d 'data={"foo": "updated value"}' \
     -H 'Authorization: Bearer <JWT>' \
     -X POST https://hub/.well-known/mercure

JWT définit les droits de publication/abonnement pour les sujets. Mercure est déployé en tant que conteneur avec une base de données externe, s'intégrant aux flux CDC.

Avantages de l'approche

  • Réutilisation du schéma : Les structures OpenAPI sont utilisées en pull et push sans duplication.
  • Temps réel : Les changements sont reflétés instantanément sans polling.
  • Évolutivité : Le hub Mercure répartit la charge.

Liste des compteurs clés pour la surveillance :

  • nofRequests — requêtes d'action.
  • nofLinksStatusNeedApprove — liens en attente d'approbation.
  • nofLinksWithUnreadComments — commentaires non lus.
  • nofPlacementCheck — vérifications de placement.

Points clés à retenir

  • SSE avec Mercure fournit des notifications push typées sans la surcharge de WebSocket.
  • CDC capture les changements de base de données en temps réel pour les processus ETL.
  • La génération automatique de types TypeScript à partir d'OpenAPI assure la cohérence des données.
  • L'approche est évolutive pour les systèmes à forte charge avec des milliers d'utilisateurs.
  • JWT dans Mercure gère l'accès aux sujets de notification.

— Editorial Team

Advertisement 728x90

Lire ensuite