Quando si parla di app mobile, rendere disponibili agli utenti i dati offline è un punto critico. Gran parte delle app sviluppate per aziende in particolare rispondono a questa esigenza. App come quelle pensate per semplificare il processo di produzione di una fabbrica, quelle ideate per servire risorse sul campo, e altro ancora. Tutti hanno bisogno di dati immediatamente disponibili per consentire di portare a termine il lavoro con successo. Come spiegato nei post precedenti, un’importante funzionalità fornita da Couchbase è la possibilità di sincronizzare i dati su più dispositivi in un modo molto semplice grazie al Sync Gateway.
Couchbase Sync Gateway
Couchbase Sync Gateway è un motore di sincronizzazione di dati fornito da Couchbase. Funziona insieme a Couchbase Server e Couchbase Lite, consentendo allo sviluppatore di sincronizzare facilmente i dati specifici dell’utente. Puoi trovare maggiori informazioni sulle sue funzionalità leggendo la documentazione ufficiale disponibile a questo link.
L’idea alla base è semplice: quando un nuovo documento viene scritto, aggiornato o eliminato nell’istanza di Couchbase Server, l’operazione viene immediatamente riflessa nel database locale dell’app. Al contrario, quando viene eseguita un’operazione nel database locale dell’app, la modifica viene immediatamente inviata a monte al server. Questo processo è reso possibile da algoritmi che forniscono una sincronizzazione avanzata e una complessa differenza tra i dati. Tutto basato su websocket.
Ora passiamo a come integrare tali funzionalità in un’app esistente che utilizza Couchbase Lite.
Installazione veloce
Innanzitutto, per provare in autonomia queste funzionalità, seguiremo alcuni passaggi per avviare ed eseguire un’istanza di Couchbase Server. Inoltre collegheremo ad essa un’istanza di Couchbase Sync Gateway. Che prenda vita il DevOps che si nasconde dentro di te!
Per questo esempio, utilizzeremo Docker, per la sua facilità d’uso.
1. Installazione con Docker Compose
In primo luogo, spostati in una directory vuota e crea un nuovo file docker-compose.yml
. In seguito, crea due directory: couchbase_demo
e couchbase_config
.
Qui hai un file Docker Compose funzionante. Eseguirà un’istanza di Couchbase Server insieme a un’istanza di Couchbase Sync Gateway. Si parleranno grazie alla rete creata da Compose. Copia e incolla questo frammento nel file docker-compose.yml
appena creato e prosegui con il passaggio successivo.
version: "3.7" services: couchbase-server: image: couchbase:community-6.0.0 ports: - "8091:8091" - "8092:8092" - "8093:8093" - "8094:8094" - "11210:11210" volumes: - "./couchbase_demo:/opt/couchbase/var" couchbase-sync-gateway: image: couchbase/sync-gateway ports: - "4984:4984" volumes: - "./couchbase_config:/tmp/config" command: /tmp/config/config.json depends_on: - couchbase-server restart: "on-failure" volumes: couchbase_demo: couchbase_config:
Ai fini di questo articolo, la configurazione di Compose richiede due volumi per funzionare correttamente. Il primo si chiama couchbase_demo
e rappresenta la directory in cui il server memorizzerà i suoi file. Il secondo invece è couchbase_config
, e conterrà un singolo file, config.json
. I volumi puntano alle directory appena create.
2. Configurazione del file con Sync Gateway
Il file config.json
contiene la configurazione che verrà letta da Sync Gateway. Viene utilizzato per determinare da quali bucket leggere, quali utenti utilizzare per le operazioni di lettura/scrittura e così via. Di seguito trovi una configurazione di esempio, che sarà utile per la configurazione del server che faremo dopo. Basta copiare e incollare questo snippet in un nuovo file config.json
all’interno della directory couchbase_config
. Ma tratteremo meglio di questo successivamente.
{ "databases": { "beers": { "server": "http://couchbase-server:8091", "bucket": "beer-sample", "username": "Administrator", "password": "password", "enable_shared_bucket_access": true, "import_docs": true, "num_index_replicas": 0, "users": { "GUEST": { "disabled": false, "admin_channels": ["*"] } } } }, "logging": { "console": { "log_level": "info", "log_keys": ["HTTP+", "CRUD", "Sync"] } } }
3. Avviare i container e configurare il server
Ora tutto ciò che devi fare è semplicemente eseguire il seguente comando nella directory che contiene il file docker-compose.yml
:
$ docker-compose up -d
Quindi, connettiti a http://localhost:8091 e ti apparirà il pannello Couchbase Server. Quindi, procedi con i seguenti passaggi:
- Fai clic su “Imposta nuovo cluster”, inserendo quindi come nome
couchbase-demo-cluster
,Administrator
come utente (se non già impostato) e come passwordpassword
. Difficile, non è vero? - Accetta i termini e fai clic su “Finish with defaults”.
- Il server è su! Vai su “Buckets” a sinistra e fai clic su “load a sample bucket with data & indexes” sul testo.
- Seleziona “beer-sample” dall’elenco dei sample disponibili e fai clic su “Load sample data”.
- Fatto! Nel menu “Buckets” vedrai il bucket “beer-sample” che viene popolato con i dati di esempio.
A questo punto il Sync Gateway dovrebbe aver riconosciuto il bucket che abbiamo creato grazie al file di configurazione fornito. Apri il tuo browser e naviga su http://localhost:4984/beers/ dovresti vedere un JSON inviato come risposta. Ce l’hai fatta!
config.json: il file di configurazione del Sync Gateway
config.json
è un file chiave per il processo che hai appena svolto. Con le proprietà che specifica puoi definire come Sync Gateway accederà ai tuoi dati, come li esporrà sotto forma di endpoint REST, come li replicherà ai tuoi mobile client e così via. Vediamo quale tipo di configurazione abbiamo applicato utilizzando il file che ti ho fornito:
- database: oggetto che contiene per ogni chiave una definizione di un bucket che sarà gestito da Sync Gateway;
- beers: chiave che rappresenta il nome dell’endpoint che stiamo esponendo. L’oggetto corrispondente contiene una configurazione aggiuntiva;
- server: l’URL che punta al Couchbase Server. Abbiamo specificato il nome del servizio definito in
docker-compose.yml
perché è l’hostname che Compose assegna al container in esecuzione; - bucket: il bucket che è esposto, al quale “beers” fa da alias;
- username: l’utente utilizzato per accedere al bucket;
- password: la password per l’utente specificato;
- enable_shared_bucket_access: impostato su
true
per abilitare la sincronizzazione dei dati con il mobile; - import_docs: lavora in funzione di
enable_shared_bucket_access
, consentendo a Sync Gateway di elaborare l’importazione dei documenti; - num_index_replicas: imposta il numero di repliche che dovrebbero avere gli indici del database. Lo impostiamo su
0
perché non abbiamo altri nodi; - users: in questo oggetto abilitiamo l’utente Guest;
- logging: definisce i tipi di logger abilitati per Sync Gateway;
- console: consente a Sync Gateway di stampare i log nello standard output;
- log_level: il livello di logging applicato al logger.
Connessione dell’SDK mobile
Tutto ciò che abbiamo ottenuto fino a qui è un’istanza in esecuzione di Couchbase Server con dati riguardanti birre e birrifici. Inoltre, abbiamo creato un’istanza di Couchbase Sync Gateway per replicare i dati di esempio sui nostri mobile client. Bene, in realtà ci manca solo un passo: il client mobile! Come abbiamo visto nel primo post, l’integrazione di Couchbase Lite è piuttosto semplice. Ora tratteremo in modo più specifico come interrogare il set di dati che è stato sincronizzato con il client.
Uno sguardo al database
Il bucket beer-sample contiene due tipi di documenti: brewery e beer. Puoi trovarli in autonomia eseguendo la seguente query N1QL nel pannello “Query” nella dashboard di Couchbase Server:
SELECT DISTINCT type FROM `beer-sample`
Sentiti libero di esplorare il set di dati! N1QL offre la stessa sintassi di un SQL standard, quindi la curva di apprendimento è molto bassa. Ad esempio, estraiamo tutte le beers disponibili nel database.
SELECT META(b).id, b.name, b.description, b.category, b.style FROM `beer-sample` AS b WHERE b.type == "beer"
La funzione META(<database_name>)
proietta i metadati della riga selezionata, consentendo di estrarre dati aggiuntivi come l’identificatore di documento predefinito. Se non è stato impostato alcun identificativo durante la creazione di un nuovo documento, Couchbase lo assegnerà per te.
Sincronizzazione di un’app Android
Ora imposta un nuovo progetto Android Studio e aggiungi l’SDK di Couchbase Lite nel tuo file build.gradle:
implementation 'com.couchbase.lite:couchbase-lite-android:2.6.0'
Come abbiamo visto nel primo post, avvia un Replicator per consentire l’avvio del processo di sincronizzazione.
// Create a new database reference, and call it “beers.db” val database = Database("beers.db", DatabaseConfiguration()) // Create a new replicator configuration, pointing to the // Sync Gateway bucket “beers”. val config = ReplicatorConfiguration( database, URLEndpoint(URI.create("ws://10.0.2.2:4984/beers")) ) // Ask for continuous replication. This will continuously sync // the database with the remote and vice-versa. config.isContinuous = true // Create a new replicator, start the replica // and keep a reference to it. val replicator = Replicator(config).apply { start() }
Il codice sopra ti fornisce un’idea su come configurare il Replicator per la sincronizzazione dei dati con l’istanza di Sync Gateway in esecuzione. L’URL di replica punta al localhost ed è pensato per essere eseguito su un emulatore Android. L’indirizzo IP specificato è l’indirizzo che Android mappa al 127.0.0.1 della macchina host.
Replica continua con il Sync Gateway
Inoltre, impostiamo la replica come continuous
. Una replica continua, come specificato nei commenti, consente al client di essere sempre aggiornato quando i dati cambiano sul bucket remoto. Viceversa, quando l’applicazione client scrive alcuni dati nel database locale, tali dati verranno automaticamente sincronizzati con il remote. Impostando il flag a false
, la sincronizzazione verrà eseguita una volta sola.
Le direzioni di replica del Sync Gateway
Le “direzioni” dei dati che abbiamo menzionato sono state battezzate con nomi specifici da Couchbase. Parliamo di una replica push quando i documenti vengono inviati dal client al server. Al contrario, parliamo di una pull replication quando i documenti sono solo scaricati dal remoto. Alla fine, la replica può avvenire in entrambe le direzioni: la replica push-and-pull è l’unione di entrambi, in cui i dati vengono trasmessi in modo bidirezionale. Quest’ultima è la scelta predefinita per l’SDK mobile.
Channels
Una funzione più interessante di Sync Gateway è offerta dai canali di sincronizzazione. Un canale è una sorta di tag che consente al gateway di instradare correttamente i dati ai vari client. Fondamentalmente, un canale è rappresentato come una stringa all’interno di un array channels
all’interno del documento. Ogni documento taggato con un determinato canale sarà visibile ai client che si sottoscrivo al gateway per esso.
Per impostazione predefinita, Sync Gateway utilizza la funzione di sincronizzazione predefinita per instradare ciascun documento nei relativi canali. Ma puoi anche personalizzare questo comportamento, scrivendo la tua funzione di sincronizzazione e includendola all’interno del file `config.json`. Ciò consente di avere un controllo granulare su come vengono inviati i dati, applicando particolari logiche di business. Puoi scoprire di più su questo argomento qui.
Dopo questa rapida panoramica, vediamo come specificare i canali nel nostro oggetto Replicator. Niente più di cosi:
config.channels = listOf("my-channel-1", "my-channel-2")
Semplice, vero?
Osservare l’avanzamento della replica verso il Sync Gateway
Quando è in corso la replica, è probabile che si debba informare l’utente sullo stato del trasferimento dei dati. L’SDK di Couchbase Lite offre fondamentalmente due modi per farlo: è possibile osservare l’avanzamento della replica, oppure l’avanzamento del trasferimento dei documenti.
È possibile collegare un change listener all’oggetto Replicator, in questo modo:
replicator.addChangeListener { change -> ... }
L’oggetto change
di tipo ReplicatorChange
ti dà accesso al Replicator
sottostante e ad un oggetto Replicator.Status
. Tale istanza ti consentirà di verificare il livello di attività della sincronizzazione, che può assumere i seguenti significati:
- Stopped: la replica è terminata o ha riscontrato un errore irreversibile.
- Offline: il Replicator non è in linea perché l’host remoto non è raggiungibile.
- Connecting: il Replicator si sta connettendo all’host remoto.
- Idle: la replica è inattiva, in attesa di modifiche o offline poiché l’host remoto non è raggiungibile.
- Busy: la replica sta trasferendo attivamente i dati.
Inoltre, hai accesso alle informazioni sull’avanzamento di una replica, rappresentato dalla classe Replicator.Progress
. L’istanza fornita ti fornirà il conteggio totale delle modifiche che verranno sincronizzate, insieme all’effettivo conteggio completato. Ti è fornita infine, anche un’istanza di CouchbaseLiteException
in caso di errore: eccezione che però non viene lanciata.
Ora è il tuo turno!
Questo articolo ti ha fornito una panoramica su come creare da zero un’istanza di Couchbase Server e un’istanza di Sync Gateway. Inoltre, ti sono stati forniti gli strumenti per integrare la potente sincronizzazione nella tua app mobile!
Tienici aggiornati sui tuoi esperimenti tramite i nostri canali social!
Ti sei perso gli altri articoli su Couchbase? Clicca qui per leggere la serie e qui per il prossimo articolo.