Zurück zur Startseite

SSE-Benachrichtigungen in SPA: Echtzeit ohne Polling

Der Artikel beschreibt die Architektur asynchroner Benachrichtigungen in SPA basierend auf SSE und Mercure. Integration mit CDC zur Verfolgung von DB-Änderungen, Wiederverwendung von OpenAPI-Schemas für die Typisierung. Code-Beispiele und Diagramme für Entwickler.

SSE Push-Benachrichtigungen in SPA: Architektur und Code
Advertisement 728x90

Asynchrone Datenaktualisierungen in SPAs mit SSE und Mercure

Frontend-Anwendungen benötigen ständige Datenaktualisierungen, um Änderungen im Backend widerzuspiegeln. Standard-API-Aufrufe erfassen den Zustand zum Zeitpunkt der Antwort, aber das Backend verarbeitet weiterhin Ereignisse: Kontenaufladungen, Inhaltsmoderation, Support-Antworten. Um dies zu lösen, werden Push-Mechanismen auf Basis von SSE verwendet, die in die bestehende OpenAPI-Spezifikation integriert sind.

Das System kombiniert einen Pull-Ansatz (periodische Anfragen) mit Push (Echtzeit-Benachrichtigungen). SSE bietet einen unidirektionalen Ereignisstrom über HTTP/2, was die Last im Vergleich zu Polling minimiert.

Anwendungsfälle für asynchrone Benachrichtigungen

Asynchrone Benachrichtigungen sind in Geschäftsprozessen entscheidend:

Google AdInline article slot
  • Kontenaufladung: Anzeige des aktuellen Stands für sofortige Käufe.
  • Inhaltsmoderation: Aktualisierung des Status nach Überprüfung.
  • Support-Antworten: Sofortige Benachrichtigung über ein neues Ticket.

In einem typischen Fall verfolgt der Nutzer – ein Werbetreibender oder Auftragnehmer – Anforderungszähler: die Anzahl der Aktionen, ungelesene Kommentare, Platzierungsprüfungen. Diese Daten sind über den API-Endpunkt /rest/User/info (operationId: getInfo) verfügbar.

/rest/User/info:
  get:
    tags:
      - User
    summary: Gibt Informationen zum aktuellen Benutzer zurück
    operationId: getInfo
    responses:
      200:
        description: Informationen zum aktuellen Benutzer
        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'

Das SeoCounters-Schema definiert die Struktur:

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

Integration von CDC und Data Platform

Änderungen in der Tabelle user_counters werden über CDC (Change Data Capture) verfolgt. Der Änderungsstrom wird an die Data Platform – ein unternehmensweites ETL-System – gesendet. Von dort werden Ereignisse über einen SSE-Hub an die Benutzeroberfläche gepusht.

Google AdInline article slot

Die Architektur verwendet ein hexagonales Modell: Die OpenAPI-Spezifikation generiert automatisch REST-Adapter und TypeScript-Typen. Für das Frontend sehen die Typen so aus:

/* Generiert von 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;
};

Diese Typen werden für die Verarbeitung von SSE-Ereignissen wiederverwendet, was Typsicherheit gewährleistet.

Implementierung von SSE in der Anwendung

SSE (Server-Sent Events) ist ein Standard für Server-Pushes, der von Browsern unterstützt wird. EventSource verbindet sich mit dem Endpunkt:

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

evtSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  // Aktualisiere den Store mit typisierten Daten
  updateSeoCounters(data.seoCounters);
};

Für Autorisierung, Themen und Skalierung wird Mercure verwendet – ein Open-Source-Hub basierend auf SSE. Der Hub akzeptiert Veröffentlichungen über REST mit JWT und sendet sie an Abonnenten.

Beispielveröffentlichung:

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 definiert Veröffentlichungs-/Abonnementrechte für Themen. Mercure wird als Container mit externer Datenbank bereitgestellt und integriert sich in CDC-Ströme.

Vorteile des Ansatzes

  • Schema-Wiederverwendung: OpenAPI-Strukturen werden in Pull und Push ohne Duplizierung genutzt.
  • Echtzeit: Änderungen werden sofort ohne Polling widergespiegelt.
  • Skalierbarkeit: Der Mercure-Hub verteilt die Last.

Liste der Schlüsselzähler für die Überwachung:

  • nofRequests – Aktionsanforderungen.
  • nofLinksStatusNeedApprove – Links, die auf Genehmigung warten.
  • nofLinksWithUnreadComments – Ungelesene Kommentare.
  • nofPlacementCheck – Platzierungsprüfungen.

Wichtige Erkenntnisse

  • SSE mit Mercure bietet typisierte Push-Benachrichtigungen ohne WebSocket-Overhead.
  • CDC erfasst Datenbankänderungen in Echtzeit für ETL-Prozesse.
  • Die automatische Generierung von TypeScript-Typen aus OpenAPI gewährleistet Datenkonsistenz.
  • Der Ansatz skaliert für hochbelastete Systeme mit Tausenden von Nutzern.
  • JWT in Mercure verwaltet den Zugriff auf Benachrichtigungsthemen.

— Editorial Team

Advertisement 728x90

Weiterlesen