Sincronizzazione dati to the Edges: una PoC con Couchbase

couchbase_sincronizzazione_dati

Presentiamo qui una Proof of Concept (PoC nel seguito) per la sincronizzazione automatica di dati tra un database centrale e dei database Lite su sistemi Android gestita con Couchbase.

Situazione

Quando a una squadra di pronto intervento (ad esempio l'equipaggio di un'ambulanza del Pronto Soccorso) viene affidata una missione, la squadra parte con il proprio mezzo, si reca sul luogo della missione e comunica con la centrale operativa i dettagli della situazione; dalla centrale operativa, poi, riceve istruzioni sul da farsi e viene indirizzata a uno dei centri di pronto intervento disponibili.

Ovviamente, affinché tutto questo sia fattibile, la squadra deve ricevere dalla centrale operativa le informazioni sul centro di pronto intervento a cui recarsi. Ad esempio, è necessario che la squadra abbia a disposizione l'indirizzo del centro.

[Ad uno stadio successivo, potrebbe essere necessario che un qualche database centrale riceva informazioni da uno dei mobile sul campo. Per il momento, al fine di semplificare la presentazione, ignoriamo questa possibile esigenza.]

L'idea è che i mezzi di pronto intervento siano muniti di un'applicazione per la gestione delle missioni che preleva i dati al database centrale e li presenta.

Un esempio potrebbe essere quello di un'ambulanza che monta un tablet con applicazione Android per la gestione delle missioni. L'equipaggio dell'ambulanza comunica con la centrale operativa mediante l'applicazione Android.

Il problema

Uno dei primi problemi che ci troviamo a dover affrontare, quindi, è quello di sincronizzare le anagrafiche centralizzate del nostro pronto intervento con le informazioni visualizzate sui vari dispositivi mobile (i tablet). La persistenza delle intere anagrafiche lato mobile sembra poco ottimale come soluzione: richiede infatti di salvare tutti i dati (e non solo quelli necessari alla missione) e presenta il problema di doverli aggiornare manualmente (o con qualche meccanismo specifico) quando questi cambiano nel database centralizzato.

Possiamo supporre, inoltre, che le anagrafiche e i servizi del pronto intervento centrale siano già implementati e ben funzionanti: non vogliamo di certo riscriverli o imbarcarci in rischiose migrazioni di database! Nella situazione in cui il pronto intervento ha già un applicativo software desktop che si connette a servizi on premises e fa riferimento ad un database relazionale, è necessario trovare un espediente per mettere le informazioni già salvate a disposizione dei client mobile.

La soluzione classica prevederebbe di scrivere un'applicazione mobile che si sincronizza con il database centralizzato, scrivere un servizio che permetta e gestisca la sincronizzazione lato backend ed il corrispondente end point lato frontend.

Il problema, in questo caso, è che risulta necessario stabilire un protocollo di comunicazione, implementare delle API, gestire la sincronizzazione e le varie casistiche nell'applicazione mobile.

Insomma, non pare di certo un lavoro facile...

Una possibile soluzione

Chi conosce Couchbase, però, sa che vi è una soluzione per un database Lite (mobile) con un efficiente servizio di sincronizzazione tra un server ed i client mobile automaticamente gestito da una componente chiamata Sync Gateway.

In altre parole, Couchbase mette a disposizione un'architettura così composta:

Il Sync Gateway è configurato per sincronizzare i database in due direzioni: dal Server ai Lite e viceversa. Nel nostro caso, in particolare, è rilevante solo la prima direzione.

Questa soluzione sembra fare al caso nostro: adottando l'architettura di Couchbase potremmo ottenere "gratis" la sincronizzazione tra il database relazionale centrale ed i vari mobile.

Se immaginiamo di avere già a disposizione la componente del database relazionale e di non poterla modificare, si rende necessario scrivere anche un nuovo, semplice servizio che travasi i dati già presenti nel database relazionale nel server Couchbase. Questo, però, risulta decisamente più facile da scrivere rispetto alla progettazione ed alla scrittura di API specifiche e di un protocollo di sincronizzazione!

L'aggiornamento delle modifiche sul database relazionale è facilmente implementato grazie agli EntityListener di CUBA: questi permettono di eseguire codice custom ogni volta che un'entità del database viene modificata. In particolare, quindi, noi sincronizziamo l'entità sul Couchbase Server con quella nel database relazionale.

Proof of Concept

Abbiamo sviluppato una Proof of Concept (PoC) per tesare la fattibilità della nostra soluzione.

L'architettura della soluzione non è probabilmente la migliore possibile: la PoC si sviluppa a partire da un backend CUBA già presente e connesso con un database PostgreSQL. Dato quindi questo punto di partenza, si è scelto di testare la componente Couchbase unicamente per quanto riguarda la sincronizzazione con il mobile. Una soluzione forse migliore prevederebbe di sostiruire totalmente il database PostgreSQL con il Couchbase. Questa soluzione non è stata implementata per evitare di dover gestire la migrazione e l'aggiornamento delle componenti dell'architettura già presenti.

La PoC prevede un'architettura come in figura:

 sincronizzazione_couchbase

Vi sono:

  • un database PostgreSQL per la persistenza dei dati centralizzati;
  • un database Couchbase Server centralizzato che replica i dati del PostgreSQL;
  • un backend CUBA che sincronizza il database relazionale con il NoSQL;
  • un Sync Gateway che sincronizza i client mobile con il Couchbase Server;
  • un'applicazione mobile con Couchbase Lite che visualizza i dati delle anagrafiche centralizzate.

Il backend è stato sviluppato con CUBA Platform ed implementa una semplice entità, detta Hospital, che simula l'anagrafica di un ospedale, riportandone nome, indirizzo e recapito telefonico.

Le componenti di data store e data sync, ovvero i database PostgreSQL e Couchbase Server, insieme con il Sync Gateway, sono configurati e rilasciati per la PoC mediante uno stack di Docker Compose.

Infine, l'applicazione mobile è stata implementata con Android Studio.

Il test della soluzione viene fatto inserendo dati dall'interfaccia utente dell'applicazione CUBA e verificandone la corretta sincronizzazione dall'applicazione mobile.

Database relazionale

Simuliamo il database relazionale mediante un database PostgreSQL.

Come detto, una possibilità diversa prevede l'utilizzo di Couchbase anche per questa funzionalità: il vantaggio di questa soluzione risiede nella pulizia e nella semplicità della soluzione. Nel caso che analizziamo, tuttavia, va considerato il fatto che un database PostgreSQL era già presente e connesso ad un'applicazione backend.

Si utilizza la versione 12 del database, e i dati sono memorizzati in un database chiamato hostpital. Il database PostgreSQL viene eseguito come servizio di uno stack di Docker Compose, dal momento che ci stiamo occupando di una PoC; per un deploy in produzione sarebbe consigliabile utilizzare un qualche container orchestrator più avanzato, ad esempio Docker Swarm o Kubernetes, e sarebbe opportuno configurare un cluster per gestire lo scaling orizzontale e la ridondanza dei dati.

Couchbase Server

Il database Couchbase Server è anch'esso dockerizzato. Utilizziamo una semplice configurazione di default per il servizio inserito nello stack di Docker Compose. Per una situazione di produzione, tuttavia, Couchbase permette di gestire un cluster che assicuri la ridondanza e la capacità di scaling orizzontale del servizio di database: anche qui è possibile utilizzare strumenti più avanzati per l'orchestrazione dei container.

Backend CUBA

Abbiamo sviluppato un servizio backend utilizzando CUBA Platform per la gestione delle anagrafiche nel database relazionale. CUBA è un framework open source che velocizza la creazione di applicazioni business. CUBA è basato sul framework Spring, usa Java Persistence API (JPA) per la gestione della persistenza dei dati e Gradle come sistema di build e gestione delle dipendenze. CUBA Platform, inoltre, genera una semplice UI mediante Vaadin che permette di visualizzare graficamente ed editare i dati.

La connessione al database Postgres viene gestita mediante JPA ed è standard.

La connessione, invece, con il server Couchbase è gestita mediante la dipendenza com.couchbase.client:java-client:${VERSION} in Gradle.

L'applicazione CUBA si connette a Couchbase Server all'avvio: una classe CouchbaseManager gestisce le operazioni di connessione al database. Couchbase mette a disposizione gli oggetti Cluster, Bucket e Collection, che permettono di scrivere i documenti (ovvero, i dati in persistenza) nel database. Il Cluster è l'oggetto a cui il backend si connette; il Bucket è invece ciò che gestisce la persistenza dei documenti nelle varie Collection. Il backend CUBA accede alle varie Collection da cui legge e scrive i dati.

Sync Gateway

Il Sync Gateway è rilasciato nello stack Docker Compose; la configurazione è specificata in un unico file JSON che include le funzioni utilizzate per validare i dati in ingresso (a questo livello, si verifica solamente che i dati non siano vuoti), la gestione della sincronizzazione solamente dei file che l'utente è autorizzato a visualizzare (autorizzazione), l'accesso dei documenti tramite l'astrazione del canale (un utente è autorizzato a leggere documenti pubblici oppure appartenenti a determinati canali).

Mobile App

L'applicazione Android è stata sviluppata con Android Studio e include la dipendenza dalla libreria Couchbase, integrando così in locale la componente Couchbase Lite per la persistenza dei dati. L'app implementa un DbManager, ovvero una componente che si prende carico dell'accesso al database, e la funzionalità di listener che configura la sincronizzazione dei dati con la componente Server mediante l'interfaccia fornita dal Sync Gateway. In questo modo, quando un documento (ovvero, un'entità di dati) viene modificata sulla componente Server, si scatena un processo di aggiornamento della componente Lite associata.

Test

Mediante la maschera messa a disposizione dall'applicazione CUBA, inseriamo nel database centrale (PostgreSQL) un ospedale di esempio:

cuba_backend_anagrafica

Lanciamo poi l'applicazione Android (la componente mobile) con un simulatore e visualizziamo l'anagrafica, che correttamente si sincronizza:

app_couchbase_sincronizzazione

Nota

Una nota finale: la soluzione qui presentata è una PoC; attualmente, AIknow Srl non gestisce deploy in produzione dell'archiettura qui descritta.