Skip to main content
View as Markdown

Abonnements en temps réel

Les composants de page liés aux données peuvent rester à jour sans rechargement complet en s'abonnant aux modifications d'enregistrements. Une source de données déclare un refreshModestatic (par défaut), poll ou realtime — et Sovrium fait le reste : le mode poll récupère à nouveau les données à intervalle régulier, le mode realtime ouvre un WebSocket (avec un repli SSE) et applique les événements insert/update/delete à mesure qu'ils arrivent. Les intégrations externes peuvent s'abonner programmatiquement via les mêmes points de terminaison.

Point de terminaison Transport
GET /api/tables/:tableSlug/subscribe Mise à niveau WebSocket (par table)
GET /api/tables/:tableSlug/subscribe/sse Repli Server-Sent Events (par table)
GET /api/realtime/subscribe WebSocket global

refreshMode sur une source de données

Définissez refreshMode sur la dataSource de n'importe quel composant. Le filter et le sort existants du composant délimitent également le flux en direct — les clients ne reçoivent que les modifications qui correspondent toujours aux critères de la source de données.

pages:
  - name: Live Dashboard
    path: /dashboard
    components:
      - type: dataTable
        dataSource:
          table: orders
          filter:
            - field: status
              operator: eq
              value: processing
          sort:
            - field: createdAt
              direction: desc
          refreshMode: realtime

Mode poll

Le mode poll récupère périodiquement à nouveau la source de données — aucun WebSocket nécessaire. Utilisez-le lorsqu'un quasi-temps-réel suffit et que la surcharge de gestion de connexion est indésirable.

dataSource:
  table: inventory
  refreshMode: poll
  pollIntervalMs: 10000 # Re-fetch every 10 seconds
Propriété Défaut Contrainte
pollIntervalMs 30000 (30 s) Minimum 1000 (1 s) pour éviter d'inonder le serveur

Mode temps réel (WebSocket)

refreshMode: realtime ouvre un WebSocket vers /api/tables/:tableSlug/subscribe. Le serveur pousse les événements de modification à mesure que les enregistrements sont créés, mis à jour ou supprimés — depuis n'importe quelle source (API REST, interface administrateur, écritures directes en base de données, automatisations).

GET /api/tables/orders/subscribe
Upgrade: websocket

Le serveur diffuse alors des messages tels que :

{ "type": "change", "event": "insert", "record": { "id": "42", "fields": {  } } }
{ "type": "change", "event": "update", "record": {  }, "oldRecord": {  } }
{ "type": "change", "event": "delete", "recordId": 42 }
{ "type": "heartbeat", "timestamp": "2026-04-05T12:00:00Z" }

Les événements insert/update portent l'enregistrement complet record (filtré côté serveur selon les permissions de champ) ; les événements delete ne portent que recordId. La connexion requiert une authentification (401 lors d'une mise à niveau non authentifiée) et un slug de table valide (404 sinon).

Filtrage des abonnements

Les abonnements respectent les filter et sort courants de la source de données, de sorte que les clients ne sont pas inondés d'événements non pertinents. Une modification qui ne correspond plus au filtre est livrée comme la transition appropriée (par ex. une mise à jour qui fait sortir une ligne de l'ensemble filtré est exposée afin que le client puisse l'abandonner).

Contrat de message

Tous les messages temps réel — les trames WebSocket et les événements SSE data: utilisent le format identique — sont une union discriminée indexée sur type.

type Objet
change Mutation insert/update/delete ; record/oldRecord utilisent la charge utile { id, fields }
conflict Une modification concurrente a écrasé un changement optimiste en attente (déclenche le toast de conflit)
heartbeat Maintien de connexion émis tous les heartbeatIntervalMs
subscribed Confirmation de handshake ; renvoie les filter/fields/subscriptionId résolus
unsubscribed Confirmation de désabonnement
join / leave Un utilisateur a ouvert/quitté une page presence: true (délimité par pagePath)
presence-sync Instantané complet de présence envoyé une fois à la connexion
connection-status Connectivité du transport (connected / reconnecting)

La charge utile record de change reflète l'enveloppe { id, fields } de l'API des enregistrements, de sorte qu'un client peut appliquer un événement à un cache lié aux données sans aucune traduction de forme. Les fields sont déjà filtrés selon les permissions de champ.

Conscience de présence

Lorsqu'une page définit presence: true, le serveur diffuse des messages join/leave/presence-sync afin que les équipes puissent voir qui d'autre consulte la même page ou table — réduisant les conflits accidentels. La présence est délimitée par pagePath.

Résolution de conflit et verrouillage optimiste

Le temps réel pilote un flux d'interface optimiste : le client applique sa modification immédiatement, puis se réconcilie avec le serveur. Si une modification concurrente a écrasé un changement optimiste en attente, le serveur émet un message conflict et la valeur canonique (le serveur l'emporte) prévaut.

Un PATCH d'enregistrement peut porter un jeton updatedAt de premier niveau. Lorsqu'il est présent, le serveur rejette une écriture obsolète avec 409 Conflict. Les tables qui y participent déclarent un champ système updated-at afin que la colonne soit automatiquement incrémentée à chaque écriture — voir CRUD et upsert.

Gestion de la connexion

Le client se reconnecte automatiquement avec le recul configuré, envoie/attend des battements de cœur et se replie sur SSE lorsque le WebSocket n'est pas disponible — de sorte que les fonctionnalités temps réel fonctionnent de manière fiable dans diverses conditions réseau.

Abonnement programmatique

Les clients externes ouvrent /api/tables/:tableSlug/subscribe (ou le /api/realtime/subscribe global) et envoient un handshake nommant la table (et, en option, subscriptionId, filter, fields). Le serveur répond par une confirmation subscribed, puis diffuse les événements change ; un désabonnement produit une confirmation unsubscribed.

Pages associées