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 refreshMode — static (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.
Constantes de transport figées. Le client et le serveur partagent REALTIME_TRANSPORT_CONFIG : recul de reconnexion [1000, 2000, 4000, 8000] ms, délai de reconnexion maximal 30000 ms, battement de cœur 30000 ms, maximum 10 connexions par utilisateur, délai d'inactivité 300000 ms, délai d'obsolescence de présence 60000 ms, maximum 50 entrées de présence par page.
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
- CRUD et upsert — le contrat de verrouillage optimiste
updatedAt - Filtrage, tri et pagination — le filtre/tri qui délimite un abonnement
- Vue d'ensemble des enregistrements — l'enveloppe
{ id, fields }que le flux reflète - Vue d'ensemble des pages — composants liés aux données et configuration de
dataSource