I sistemi di trasformazione digitale presentano frequentemente architetture complesse in cui i vari componenti devono comunicare fra di loro, spesso in tempo reale.
Alcuni esempi di questo tipo di comunicazioni sono:
- Messaggistica integrata con l’applicazione, stile WhatsApp.
- Notifica di eventi rilevati da sistemi IoT come allarmi, stato degli impianti, eccetera.
- Comunicazione del cambio di stato di un documento da una sessione alle altre.
- Acquisizione di informazioni dal backend da parte di un device.
- Allineamento di un database offline con la controparte cloud.
Instant Developer Cloud include un sistema di sincronizzazione e di scambio di messaggi fra sessioni applicative e device in grado di risolvere i casi sopra indicati. Le caratteristiche principali sono le seguenti:
- Gestione automatica della connessione con la controparte nel cloud.
- Scambio di messaggi in tempo reale fra sessioni e applicazioni.
- Gestione di messaggi in modalità offline.
- Gestione di operazioni remote sui documenti.
- Sincronizzazione dello stato dei documenti fra database offline e backend cloud.
Architettura delle sessioni #
La sincronizzazione mette in comunicazione le varie sessioni applicative, sia quelle in esecuzione nel server nel cloud, che quelle in esecuzione nei device degli utenti. Le prime vengono chiamate sessioni online, le seconde sessioni offline o sessioni locali.
È importante notare che dal termine sessione offline deriva il concetto di applicazione offline utilizzato in questa documentazione. Si definisce infatti applicazione offline un’applicazione in grado di funzionare anche in assenza di connessione internet e che può essere sincronizzata con il server ogni volta che il device in cui è installata si riconnette a internet.
Per far sì che una sessione locale possa comunicare con le altre sessioni, sia quelle online che quelle locali nei dispositivi, la sincronizzazione crea per ogni dispositivo connesso una sessione proxy nel cloud. Si chiama proxy perché essa rappresenta il device all’interno del server per quanto riguarda le operazioni di sincronizzazione.
Lo schema alla pagina seguente illustra la connessione tra le sessioni di vario tipo: se, ad esempio, la sessione server riceve un evento IoT come l’attivazione di un allarme, essa può comunicarlo a tutte le sessioni interessate, sia quelle online che quelle locali, in esecuzione nei device.
L’invio dei messaggi ai device potrà avvenire anche se sono momentaneamente offline, in quanto sia il server nel cloud che i device possiedono un data store della sincronizzazione che memorizza i messaggi non volatili in modo che possano essere consegnati anche se la connessione non era attiva al momento dell’invio.
Le sessioni locali e online possono appartenere anche ad applicazioni diverse. Ad esempio l’applicazione nel server può essere quella di back office, mentre quella sui device viene usata dagli utenti finali. Nel server, inoltre, possono essere presenti più applicazioni diverse e la sincronizzazione può essere configurata per inviare messaggi anche tra sessioni che non appartengono alla stessa applicazione. Questo può essere utile se le varie applicazioni modificano gli stessi dati o appartengono allo stesso sistema informativo.
Configurazione della sincronizzazione #
Il sistema di sincronizzazione deve essere configurato per ogni tipo di sessione, sia nel server che per quelle locali ai device. In questo paragrafo viene analizzata la configurazione base per attivare la sincronizzazione; nei paragrafi successivi verranno aggiunti ulteriori parametri in funzione dei servizi che si desidera utilizzare.
Sessioni online #
Per le sessioni online, la configurazione della sincronizzazione deve avvenire all’inizio della sessione, quindi:
- Nell’evento app.onStart per le sessioni di tipo browser o di tipo server.
- Nell’evento app.onCommand per le sessione di tipo REST.
- Nell’evento app.sync.onConnect per le sessioni di tipo proxy.
La prima proprietà da configurare negli eventi di inizio sessione è app.sync.dataStore, che serve per comunicare alla sincronizzazione il database da utilizzare per memorizzare i messaggi permanenti, cioè quelli che devono essere inviati ai device anche se sono momentaneamente disconnessi. Ad esempio:
app.sync.dataStore = App.NwindDB;
La seconda proprietà è relatedApps, che rappresenta il nome dell’installazione delle altre applicazioni che devono ricevere i messaggi di sincronizzazione, impostate come stringa o array di stringhe. Questa proprietà deve essere impostata solo se nel server sono installate due o più applicazioni che trattano gli stessi dati da sincronizzare. Ad esempio:
app.sync.relatedApps = “backoffice”;
La terza proprietà è topics, un oggetto JavaScript che rappresenta i messaggi ai quali è interessata la sessione. Ogni sessione, infatti, non deve ricevere tutti i messaggi delle altre sessioni, ma solo quelli che la riguardano direttamente. I topics verranno spiegati nei paragrafi successivi. Ecco un esempio:
app.sync.topics = [“utente0”, “utente10”, “utente2”];
Sessioni locali (offline) #
In aggiunta alle proprietà delle sessioni online, quelle locali devono specificare serverUrl e appName, di solito nell’evento onStart. La prima rappresenta il server nel cloud a cui ci si deve collegare, la seconda il nome dell’installazione dell’applicazione che gestisce la sincronizzazione. Ad esempio:
if (app.runsLocally()) {
app.sync.serverUrl = app.sync.serverUrl ||
"https://myserver.instantdevelopercloud.com";
app.sync.appName = "backoffice";
}
Il metodo app.runsLocally restituisce true se la sessione è locale, così da poter inserire il codice aggiuntivo solo in questo caso.
Si noti che serverUrl viene impostata solo se è vuota, perché il framework di Instant Developer Cloud può preimpostare questa proprietà quando l’applicazione viene lanciata dall’IDE in anteprima FEBE (Front End – Back End).
Infine è possibile impostare la proprietà autoConnect, che rappresenta la modalità di gestione della connessione. Il valore di default è App.Sync.autoConnectTypes.automatic, che crea una connessione solo al bisogno e poi la disattiva dopo un tempo prestabilito di inattività.
Nella pratica comune, però, è preferibile lasciare la sessione sempre connessa al server di sincronizzazione in modo che possa rimanere aggiornata in tempo reale. Per ottenere questo risultato, inserire il seguente codice:
app.sync.autoConnect = App.Sync.autoConnectTypes.alwaysConnected;
Attivazione della sincronizzazione #
Mentre le sessioni online sono sempre connesse al proprio sistema di sincronizzazione, per quelle locali la sincronizzazione deve essere esplicitamente attivata tramite la proprietà enabled. Quindi, dopo aver impostato le proprietà di configurazione, quando si deve attivare la sincronizzazione occorre scrivere il seguente codice:
app.sync.enabled = true;
Fintanto che questa proprietà rimane attiva, la sessione locale gestirà la sincronizzazione. Questo non significa che il device rimarrà sempre connesso al server. Esso si può disconnettere e poi riconnettere in automatico, a seconda del valore della proprietà autoConnect, dello stato della connessione e dello stato del device.
Si segnala che se la proprietà autoConnect è impostata a App.Sync.autoConnectTypes. manual l’attivazione della proprietà enabled non apre mai la connessione; sarà necessario usare i metodi connect e disconnect dell’oggetto sync per gestirla.
Nell’immagine seguente viene riportato il ciclo di vita della connessione all’interno di una sessione locale.
Attivazione della connessione #
Quando il framework tenta di aprire la connessione, viene contattata l’applicazione specificata del server di sincronizzazione e, lato server, viene creata una sessione proxy relativa al device che sta tentando di aprire la connessione.
Nella sessione proxy, cioè lato server, viene notificato l’evento app.sync.onConnect che permette alla sessione di determinare se il device ha il diritto di connettersi o meno. Se nel codice dell’evento viene attivata la proprietà cancel del parametro options, la connessione lato device viene chiusa e la proprietà app.sync.enabled della sessione locale viene disattivata per evitare inutili tentativi di riconnessione. In questo caso anche la sessione proxy viene terminata immediatamente.
Si noti che viene aspettato il completamento dell’evento onConnect prima di dare il consenso al device, quindi è necessario che il codice interno all’evento non richieda troppo tempo per essere eseguito. In caso contrario, può scattare il timeout di connessione della sessione locale che per default è 5000 ms, valore modificabile tramite la proprietà app.sync.connectionTimeout.
Se si verifica un timeout di connessione mentre la connessione al server è già attiva, nella sessione locale viene resettata la proprietà app.sync.enabled. Infatti, il verificarsi del timeout è determinato dal fatto che l’evento onConnect lato server è stato troppo lento e questo può essere segno di un sovraccarico. Tentando di nuovo la connessione, il sovraccarico potrebbe aumentare.
La stessa cosa avviene se l’evento onConnect lato server genera un’eccezione. Anche in questo caso è bene che la sessione locale non tenti di nuovo la connessione in maniera automatica.
In ogni caso, al termine del tentativo di connessione, la sincronizzazione notifica l’evento app.sync.onConnect anche alla sessione locale passando come parametri lo stato della connessione e l’eventuale motivo della mancata connessione da parte del server.
Vediamo un esempio di codice di onConnect nelle sessioni online.
app.sync.onConnect = function (options)
{
// Solo online!
if (!app.runsLocally()) {
app.sync.dataStore = "ToBuyDB";
// Carico l’utente in base ai dati passati come topics
if (app.sync.topics)
app.account = yield App.TBBE.Account.loadByKey(app, app.sync.topics);
//
if (!app.account) {
options.cancel = true;
options.cancelReason = “User not found”;
}
}
};
Chiusura della connessione #
Dopo che la connessione è stata instaurata, essa viene gestita in automatico dal sistema di sincronizzazione. Ci sono alcune situazioni in cui la connessione viene chiusa:
- Mancanza di segnale di rete del device.
- Applicazione in background.
- Device bloccato.
- app.sync.enabled impostata a false.
- se autoConnect non è “automatic”, dopo il timeout di inutilizzo della sincronizzazione, che per default è 30 secondi.
In tutti questi casi, viene lanciato l’evento onDisconnect sia nella sessione locale che in quella online e poi quest’ultima viene terminata. Se il device effettua un altro tentativo di connessione, esso avverrà su una sessione proxy diversa dalla precedente.
L’evento onDisconnect della sessione locale può essere utilizzato per avvertire l’utente che la sincronizzazione non è disponibile. Questo può essere utile soprattutto se l’applicazione non ha dati locali ma si basa su chiamate remote al server.