Una live query è una sottoscrizione a una query sul database: il server spinge gli eventi create, update e delete delle righe corrispondenti. È il tempo verbale che mancava all’accesso ai dati: le query normali parlano al passato (“che cosa corrispondeva nel momento della richiesta”), le live queries parlano al presente continuo (“che cosa corrisponde, mentre cambia”). Lo schermo smette di chiedere e inizia a restare giusto.
Punti chiave
| Domanda | Risposta |
|---|---|
| Che cos’è | Una query permanente – una sola sottoscrizione, e arriva ogni cambiamento dei suoi risultati |
| I cinque eventi | create · update · delete · enter · leave |
| Sotto il cofano | Change stream del database → matching dei predicati → push su WebSocket |
| vs. il polling | Latenza da tempo reale, payload della dimensione del delta, nessun carico di query per intervallo |
| vs. i socket grezzi | Il livello di query: matching, eventi tipizzati, permessi, riconnessioni |
La sottoscrizione, in codice
Il gesto che definisce tutto – prendere la query che già esisteva e sottoscriverla:
// JavaScript / Node.js — Back4app JS SDK
// A live query: subscribe to a QUERY and receive its changes as events
const query = new Parse.Query('Task');
query.equalTo('assignee', currentUser);
const sub = await query.subscribe();
sub.on('create', (t) => addRow(t)); // new match appeared
sub.on('update', (t) => refreshRow(t)); // a match changed
sub.on('enter', (t) => addRow(t)); // edited INTO the result set
sub.on('leave', (t) => removeRow(t)); // edited OUT of the result set
sub.on('delete', (t) => removeRow(t)); // a match was deleted // Flutter / Dart — Back4app Flutter SDK
// A live query: subscribe to a QUERY and receive its changes as events
final liveQuery = LiveQuery();
final query = QueryBuilder<ParseObject>(ParseObject('Task'))
..whereEqualTo('assignee', currentUser);
final sub = await liveQuery.client.subscribe(query);
sub.on(LiveQueryEvent.create, (t) => addRow(t)); // new match
sub.on(LiveQueryEvent.update, (t) => refreshRow(t)); // match changed
sub.on(LiveQueryEvent.enter, (t) => addRow(t)); // edited into the set
sub.on(LiveQueryEvent.leave, (t) => removeRow(t)); // edited out of the set // iOS / Swift — Back4app Swift SDK
// A live query: subscribe to a QUERY and receive its changes as events
let query = Task.query("assignee" == currentUser)
let subscription = query.subscribeCallback
subscription?.handleEvent { _, event in
switch event {
case .created(let t): addRow(t) // new match appeared
case .updated(let t): refreshRow(t) // a match changed
case .entered(let t): addRow(t) // edited INTO the result set
case .left(let t): removeRow(t) // edited OUT of the result set
case .deleted(let t): removeRow(t)
}
} // Android / Kotlin — Back4app Android SDK
// A live query: subscribe to a QUERY and receive its changes as events
val client = ParseLiveQueryClient.Factory.getClient()
val query = ParseQuery.getQuery<ParseObject>("Task")
query.whereEqualTo("assignee", currentUser)
val sub = client.subscribe(query)
sub.handleEvent(SubscriptionHandling.Event.CREATE) { _, t -> addRow(t) }
sub.handleEvent(SubscriptionHandling.Event.UPDATE) { _, t -> refreshRow(t) }
sub.handleEvent(SubscriptionHandling.Event.ENTER) { _, t -> addRow(t) }
sub.handleEvent(SubscriptionHandling.Event.LEAVE) { _, t -> removeRow(t) } Il vocabolario degli eventi merita la sua tabella, perché enter e leave sono ciò che fa di questa la sottoscrizione a una query e non la notifica di una tabella:
| Evento | Scatta quando… | Esempio (sottoscrizione a “attività assegnate a me”) |
|---|---|---|
| create | Un nuovo record corrisponde | Viene creata un’attività assegnata a me |
| update | Un record corrispondente cambia | Lo stato della mia attività cambia |
| enter | Una modifica fa corrispondere un record esistente | Un’attività viene riassegnata a me |
| leave | Una modifica fa smettere di corrispondere | La mia attività viene riassegnata ad altri |
| delete | Un record corrispondente viene eliminato | L’attività viene rimossa |
La pipeline dietro il push
Due metà, separabili con pulizia: la sorgente dei cambiamenti – il feed di scritture del database stesso (change streams negli archivi documentali, log di replica altrove) – e il livello di matching, che confronta ogni cambiamento con ogni predicato registrato e spinge esattamente verso i sottoscrittori i cui risultati sono cambiati, con i permessi applicati per singolo sottoscrittore. Il protocollo aperto LiveQuery è un’implementazione di riferimento leggibile di tutta questa forma.
Live queries vs. polling vs. SSE vs. WebSocket
| Approccio | Latenza | Payload | Costo lato server | Da costruire |
|---|---|---|---|---|
| Polling | Intervallo di poll | Riscaricamento completo ogni volta | Query × client × frequenza | Timer, diffing |
| Long polling | Quasi tempo reale | Risposta completa per evento | Connessioni trattenute | Tubature di ripiego |
| SSE | Tempo reale | Delta | Stream, a senso unico | Progetto degli eventi |
| WebSocket grezzi | Tempo reale | Quello che si definisce | Connessioni + il fan-out in proprio | Tutto |
| Live queries | Tempo reale | Eventi per singolo cambiamento | Matching + connessioni (gestiti) | La query |
L’ultima colonna è l’argomento: con i socket grezzi restano da costruire il protocollo dei messaggi, l’instradamento, le verifiche dei permessi e il recupero dopo la riconnessione; con le live queries il predicato è il protocollo e il resto appartiene alla piattaforma.
Casi d’uso tipici
- Chat e caselle di posta – si sottoscrivono i messaggi della conversazione; l’arrivo è un evento, non un aggiornamento manuale.
- Dashboard in diretta – ordini, metriche, flotte: la query definisce la vista, gli eventi la tengono vera.
- App collaborative – bacheche di attività e documenti condivisi, dove le modifiche di cinque persone si intrecciano in pochi secondi.
- Presenza e stato – chi è online, che cosa è in corso: enter e leave fanno qui il loro lavoro di precisione.
- Schermate operative – console di supporto e viste di amministrazione che devono rispecchiare la produzione adesso, non all’ultimo aggiornamento.
Polling, push o sottoscrizione? Matrice decisionale
| Scegliere le live queries quando… | Bastano strumenti più semplici quando… |
|---|---|
| Gli utenti guardano dati condivisi che cambiano | I dati cambiano raramente – poll gentile o ricarica al ritorno del focus |
| I cambiamenti arrivano da molti autori e percorsi | Un solo autore potrebbe semplicemente spingere via SSE |
| La vista è naturalmente una query | Il messaggio non ha la forma di dati – meglio i socket diretti |
| I permessi devono filtrare ciò che vede ognuno | Tutto è trasmissione pubblica |
| L’infrastruttura di fan-out non vale la pena di gestirla | È già in esercizio una piattaforma di tempo reale |
La disciplina lato client che tiene sane le sottoscrizioni, qualunque sia la scelta: sottoscrivere in modo ristretto (predicati selettivi su campi indicizzati) e disiscriversi quando la schermata si chiude – le query permanenti sono stato sul server, e le schermate che le lasciano filtrare accumulano costi in modo invisibile.
Limiti e trade-off
- Il matching è un carico di lavoro reale. Ogni scrittura viene confrontata con i predicati registrati; migliaia di sottoscrizioni larghe su classi molto sollecitate lo moltiplicano – la selettività è la leva.
- Le connessioni sono stato. La flotta di socket ha bisogno di affinità, heartbeat e backplane di fan-out – le piattaforme gestite esistono proprio perché questo è lavoro pesante e indifferenziato.
- Le riconnessioni richiedono un recupero. Un client che era offline ha perso degli eventi; i flussi robusti rieseguono la query di base alla ri-sottoscrizione invece di dare per buono che nel buco non sia successo nulla.
- Ordine e consegna hanno la forma dell’at-least-once. Handler di eventi idempotenti (applicare per ID dell’oggetto, non per accodamento) assorbono con eleganza il duplicato occasionale.
- Non tutto chiede una sottoscrizione. I dati guardati raramente e cambiati raramente sono territorio del polling; le live queries si guadagnano il loro costo dove occhi e scritture sono entrambi frequenti.
Le live queries su Back4app
Back4app è una piattaforma open-source di Backend as a Service (BaaS) che combina database gestito, API REST e GraphQL generate automaticamente, autenticazione, archiviazione di file e funzioni serverless con Cloud Code. Live Query ne è il livello di tempo reale, e le schede di codice qui sopra sono tutta la storia lato client: lo stesso query builder già in uso, una sola chiamata di sottoscrizione, cinque eventi tipizzati – con le ACL verificate per singolo sottoscrittore, così che il tempo reale non scavalchi mai il modello dei permessi, e con flotta di WebSocket, change stream e fan-out che girano come infrastruttura gestita. Basta abilitare Live Query su una classe nella dashboard e sottoscrivere da qualsiasi SDK: il presente continuo diventa una feature, non un progetto.
Domande frequenti
Che cos'è una live query?
Una sottoscrizione permanente a una query sul database: invece di chiedere una volta e ottenere un'istantanea, si sottoscrive la query e il server spinge un evento ogni volta che il suo insieme di risultati cambia – un record corrispondente creato, aggiornato, eliminato, oppure modificato fino a entrare nei risultati o a uscirne. Lo schermo smette di fare polling e si mette ad ascoltare.
In che cosa una live query differisce da una query normale?
Nella durata. Una query normale si esegue, restituisce e finisce lì – la sua risposta inizia a invecchiare immediatamente. Una live query resta registrata sul server: i risultati iniziali arrivano allo stesso modo, poi eventi di cambiamento mirati li tengono aggiornati fino alla disiscrizione. Stesso linguaggio di predicati, rapporto opposto con il tempo.
Come funzionano le live queries sotto il cofano?
Due metà unite: una sorgente di cambiamenti e un trasporto. Il database emette il proprio flusso di scritture – tramite change stream, log di replica o trigger – e un server di sottoscrizioni confronta ogni cambiamento con i predicati di query registrati, spingendo gli eventi pertinenti ai sottoscrittori via WebSocket. L'SDK client incapsula il ciclo di vita del socket, così il codice applicativo vede soltanto eventi tipizzati.
Che cosa sono gli eventi enter e leave?
La coppia sottile che rende precisa la sottoscrizione a una query. Enter scatta quando un record esistente viene modificato e inizia a corrispondere al predicato; leave scatta quando una modifica lo fa smettere di corrispondere. Un'attività riassegnata a me entra nella sottoscrizione "assegnate a me" senza essere stata creata; riassegnata ad altri, ne esce senza essere stata eliminata. Create, update e delete coprono il resto.
Perché le live queries sono meglio del polling?
In tre modi contemporaneamente: la latenza – i cambiamenti arrivano in tempo reale invece che al poll successivo; la banda – gli eventi trasportano solo ciò che è cambiato invece di riscaricare tutto; e il carico – il server fa un matching per singolo cambiamento invece di eseguire query complete per client e per intervallo. Fare polling ogni pochi secondi è una simulazione; la sottoscrizione è il tempo reale vero.
Che cosa aggiungono le live queries rispetto ai WebSocket grezzi?
Il cervello delle query. Un socket grezzo muove messaggi; tutto il resto – quali client si interessano a quali cambiamenti, che cosa significano gli eventi, chi ha il diritto di vedere che cosa, il recupero dopo una riconnessione – resta da scrivere. Un livello di live queries fa il matching dei predicati lato server, tipizza gli eventi, applica i permessi per singolo sottoscrittore e gestisce il ciclo di vita del socket. È la differenza fra un trasporto e una feature.
Le subscription GraphQL sono la stessa cosa delle live queries?
Stessa famiglia, trigger diverso. Le subscription GraphQL scattano su eventi nominati definiti a mano – una mutation pubblica, i sottoscrittori ricevono. Le live queries scattano sui cambiamenti dell'insieme di risultati di una query – nessun cablaggio di eventi, il predicato è la sottoscrizione. Entrambe viaggiano su WebSocket; le live queries scambiano la progettazione esplicita degli eventi con una copertura automatica di ogni percorso di scrittura.
Come scalano le live queries?
Su due assi: le connessioni – migliaia di socket aperti distribuiti fra server di sottoscrizioni dietro un backplane pub/sub – e il matching: ogni scrittura viene confrontata con i predicati registrati, ed è per questo che contano sottoscrizioni selettive su campi indicizzati. Le piattaforme gestite fanno girare entrambi gli assi; la disciplina lato client sta nel sottoscrivere in modo ristretto e disiscriversi quando la schermata si chiude.