This post looks at how you get started with data replication/synchronization across iOS devices using Couchbase Mobile. The Couchbase Mobile Stack comprises of Couchbase Server, Sync Gateway and Couchbase Lite embedded NoSQL Database. In an earlier post, we discussed how Couchbase Lite can be used as a standalone embedded NoSQL database in iOS apps. This post will walk you through a sample iOS app in conjunction with a Sync Gateway that will demonstrate the core concepts of Push & Pull Replication, Authentication & Access Control, Channels and Sync Functions.

While we will be looking at data synchronization in the context of an iOS App in Swift, everything that’s discussed here applies equally to mobile apps developed in any other platform (Android, iOS (ObjC), Xamarin). Deviations will be specified as such.

NOTE:  We will be discussing Couchbase Mobile v1.4 which is the current production release. There is a newer Developer Preview version 2.0 of Couchbase Mobile that has a lot of new and exciting features.

Couchbase Mobile

The Couchbase Mobile Stack comprises the Couchbase Server, Sync Gateway and Couchbase Lite embedded NoSQL Database. This post will discuss the basics of NoSQL data replication and synchronization using Couchbase Mobile. I’ll assume you’re familiar with developing iOS Apps, basics of Swift, some basics of NoSQL and have some understanding of Couchbase. If you want to read up more on Couchbase Mobile, you can find lots of resources at the end of this post.

Couchbase Sync Gateway

The Couchbase Sync Gateway is an Internet-facing synchronization mechanism that securely syncs data across devices as well as between devices and the cloud.

It exposes a web interface that provides

  • Data Synchronization across devices and the cloud
  • Access Control
  • Data Validation

You can use any HTTP client to further  explore the interface. Check out this post on using Postman for querying the interface.

There are three main concepts related to data replication or synchronization using the Sync Gateway –

Channel

A channel can be viewed as a combination of a tag and message queue. Every document can be assigned to one or more channels. Documents are assigned to channels which specify who can access the documents. Uses are granted access to one or more channels and can only read documents assigned to those channels. For details, check out the documentation on Channels.

 

Sync Function

The sync function is a JavaScript function that runs on the Sync Gateway. Every time a new document, revision or deletion is added to a database, the sync function is called. The sync function is responsible for

  •  Validating the document,
  • Authorizing the change
  • Assigning document to channels and
  • Granting users’ access to channels.

For details, check out documentation on Sync Function .

 

Replication

Replication a.k.a Synchronization is the process of synchronizing changes between local database and remote Sync Gateway. There are two kinds –

  • Push Replication is used to push changes from local to remote database
  • Pull Replication is used to pull changes from remote to local database

For details, check out documentation on replications.

 

Installation of Couchbase Sync Gateway

Follow the installation guide to install the Sync Gateway.

Launch your Sync Gateway with the following config file. The exact location of the config file will depend on the platform. Please refer to the install guide for the same.

Sync Gateway Config File

Here are some key points to note in the configuration file:-

  • Line 8: The “walrus:” value for “server”  indicates that the Sync Gateway should persist data in-memory and is not backed by a Couchbase server.
  • Line 11: Guest user access is disabled
  • Line 12-13: There are two users, “Jane” and “Joe” configured in the system. Both users have access to a “_public” channel and each has access to their own private channel.
  • Line 22-100: A simple sync function that does the following
    1. Line 29-36 : Document validation to ensure that the document contains user defined “tag” and “owner” properties
      1. The “tag” property is used to specify if the document is publicly available to any user or if it is private to a user
      2. The “owner” property is used to specify if the document is publicly available to any user or if it is private to a user
    2. Line 46: Give user’s access to the “_public” and a private channel (identified using owner of document)
    3. Line 51-56 : If it’s a document update, verify that the “tag” property is unchanged across revisions
    4. Line 66: Assign all documents with “public” tag to the “_public” channel
    5. Line 72: Assign all documents with a tag other than “public” to the private channel
      1. Line 75: For private channel documents, first verify that the document’s owner is the one making the request

Couchbase Lite

The Couchbase Lite is an embedded NoSQL database that runs on devices. Couchbase Lite can be used in several deployment modes. The Getting Started with Couchbase Lite  post discusses the standalone deployment mode. Couchbase Lite can be used in conjunction with a remote Sync Gateway that would allow it to sync data across devices. This post discusses the deployment mode using a Sync Gateway.

There are many options to integrate Couchbase Lite framework into your iOS App. Check out our Couchbase Mobile Getting Started Guide for the various integration options.

Native API

Couchbase Lite exposes a native API for iOS, Android and Windows that allows the Apps to easily interface with the Couchbase platform. As an App Developer, you do not have to worry about the internals of  the Couchbase Lite embedded database, but you can instead focus on building your awesome app . The native API allows you to interact with the Couchbase Lite framework just as you would interact with other platform frameworks/ subsystems. Again, we will be discussing Couchbase Mobile v1.4 in this blog post. You can get a full listing of the APIs on our Couchbase Developer site.

Demo iOS App

Please download the Demo Xcode project from this Github repo and switch to “sync support” branch. We will use this app as an example in the rest of the blog. This app uses Cocoapods to integrate the Couchbase Lite framework.

 

Synchronization of Documents Across Users

  1. Build and Launch the App. You should be presented with a Login alert
  2. Enter user “jane” and password of “password” . This user was configured in the Sync Gateway config file
  3. Add first document by tapping on the “+” button on top right hand corner.
    1. Give a name to document and a one line description.
    2. Use tag “private”.
    3. Behind the scene, the Push Replicator pushes the document to the Sync Gateway and is processed by the Sync Function. Based on the tag, the Sync function assigns the document to the user’s private channel.
  4. Add second document by tapping on the “+” button on top right hand corner.
    1. Give a name to document and a one line description
    2. Use tag “public”.
    3. Behind the scene, the Push Replicator pushes the document to the Sync Gateway and is processed by the Sync Function. Based on the public tag, the Sync function assigns the document to the public channel
  5. Now “log off” Jane . You will be presented with the Login alert again
  6. Enter user “joe” and password of “password” . This user was also configured in the Sync Gateway config file
  7. The public document that was created by Jane will be listed.
    1.  Behind the scenes, the Pull Replicator pulls all the documents from Joe’s private channel and the public channel. The public document that was created by Jane is pulled. However, since Joe did not have access to Jane’s private channel, the private document created by Jane is not pulled.

To verify the state of things on the Sync Gateway, you can use query the Admin REST interface using Postman or any HTTP client.

This is the CURL request to the Sync Gateway

The Response from the Sync Gateway shows the two documents assigned to the public and Jane’s private channel respectively

 

Exploring the Code

Now, lets examine relevant code snippets of the iOS Demo App –

Opening/ Creating a per-user Database 

Open DocListTableViewController.swift file and locate openDatabaseForUser function.

  1. Specify the options to associate with the database. Explore the other options on CBLDatabaseOptions class.
  2. Create a database with name of the current user. This way, every user of the app will have their own local copy of the database. If a database exists with the name, a handle to existing database will be returned else a new one is created. Database Names must to be lowercase. If success, a new local database will be created if it does not exist. By default, database will be created in the default path (/Library/Application Support). You can specify a different directory when you instantiate the CBLManager class.
  3. Start Database Replication Process for given user credentials. We will discuss Replication code in detail in the following sections.

Fetching Documents

Open the DocListTableViewController.swift file and locate getAllDocumentForUserDatabase  function.

  1. Get handle to database with specified name
  2. Create a query object. This Query is used to fetch all documents. The Sync Function on the Sync Gateway will ensure that documents are pulled  from only the channels  that are accessible to the user. You can create a regular query object or a “live” query object. The “live” query object is of type CBLLiveQuery that  automatically refreshes everytime the database changes in a way that affects the query results. The query has a number of properties that can be tweaked in order to customize the results. Try modifying the properties and seeing the effect on results
  3. You will have to explicitly add an observer to the Live Query object be notified of changes to the database. We will discuss this more on section on “Observing Local & Remote Synchronized Changes to Documents”. Don’t forget to remove the observer and stop observing changes when you no longer need it!
  4. Execute the query asynchronously. You can also do it synchronously if you prefer , but its probably recommended to do it async if the data sets are large.

Once the query executes successfully, you get a CBLQueryEnumerator object. The query enumerator allows you to enumerate the results. It lends itself very well as a data source for the Table View that displays the results

Observing Local & Remote Synchronized Changes to Documents 

Open the DocListTableViewController.swift file and locate the addLiveQueryObserverAndStartObserving function.

Changes to the database could be as a result of the user’s actions on the local device or could be a result of changes synchronized from other devices.

  1. In order to be notified of changes to the database that affect the Query results, add an observer to the Live Query object . We will instead leverage iOS’s Key-Value-Observer pattern to be notified of 
changes. Add a KVO observer to the Live Query object to start observing changes to the “rows” property on Live Query object This is handled through appropriate Event Handler APIs on other platforms such as the addChangeListener function on Android/Java.
  2. Start observing changes .

Whenever there is a change to the database that affects the “rows” property of the LiveQuery object, your app will be notified of changes. When you receive the notification of change, you can update your UI, which in this case would be reloading the tableview.

 

Authentication of Replication Requests

Open DocListTableViewController.swift file and locate startDatabaseReplicationForUser function.

All Replication requests must be authenticated. In this app, we use HTTP Basic Authentication.

There are several Authenticator types namely – Basic, Facebook, OAuth1, Persona, SSL/TLS Cert.

Pull Replication

Open DocListTableViewController.swift file and locate startPullReplicationWithAuthenticator function.

  1. Create a Pull Replicator to pull changes from remote Sync Gateway. The kRemoteSyncUrl is the URL of the remote database endpoint on the Sync Gateway.
  2. Associate Authenticator with the Pull Replication. Optionally one can set the channels from which documents should be pulled
  3. Setting replication to “continuous” will allow change updates to be pulled indefinitely unless explicitly stopped or database is closed.
  4. Start the Pull Replication

Push Replication

Open DocListTableViewController.swift file and locate startPushReplicationWithAuthenticator function.

  1. Create a Push Replicator to push changes to remote Sync Gateway. The kRemoteSyncUrl is the URL of the remote database endpoint on the Sync Gateway.
  2. Associate Authenticator with the Push Replication.
  3. Setting replication to “continuous” will allow change updates to be pushed indefinitely unless explicitly stopped or database is closed.
  4. Start the Push Replication

Monitoring the Status of the Replication

Open the DBListTableViewController.swift file and locate addRemoteDatabaseChangesObserverAndStartObserving function.

 

You can monitor the status of the replication by adding an observer to the iOS Notification Center to be notified of cblReplicationChange notifications . You could use the notification handler for instance, to display appropriate progress indicators to user.  This is handled through appropriate Event Handler APIs on other platforms such as the addChangeListener function on Android/Java.

What Next ?

We would love to hear from you. So if you have questions or feedback, feel free to reach out to me at Twitter @rajagp or email me priya.rajagopal@couchbase.com. If you would like to enhance the demo app, please submit a pull request to the Github Repo.

The Couchbase Mobile Dev Forums is another great place to get your mobile related questions answered .Check out the development portal for details on the Sync Gateway and Couchbase Lite . Everything that was discussed here is on the Context of Couchbase Mobile 1.4. There are a lot of new and exciting changes coming up on Couchbase Mobile 2.0. Be sure to check out the  Developer Preview version 2.0 of Couchbase Mobile.

Author

Posted by Priya Rajagopal, Senior Director, Product Management

Priya Rajagopal is a Senior Director of Product Management at Couchbase responsible for developer platforms for the cloud and the edge. She has been professionally developing software for over 20 years in several technical and product leadership positions, with 10+ years focused on mobile technologies. As a TISPAN IPTV standards delegate, she was a key contributor to the IPTV standards specifications. She has 22 patents in the areas of networking and platform security.

4 Comments

  1. Hello Priya..!!!

    That was a really nice post for data sync in Swift.If you can provide in objective C too, it would be appreciated.

  2. Hello Priya,

    Downloaded and installed the UserProfileDemo app for Xamarin.Tried testing it by running on two simulators simultaneously sorry to say that, the application doesn’t work as expected. Data not getting synced when logged in with the same credentials on the other simulator.It gets fetch the data from local db every time but no global syncing works .Please help me regarding this.

  3. Your comment seems unrelated to this blog post and tutorial (which is in fact for native iOS on Couchbase Mobile 1.4). Did you follow instructions in this Xamarin tutorial ? https://docs.couchbase.com/userprofile-couchbase-mobile/sync/userprofile/xamarin/userprofile_sync.html. If you are running into issues with that tutorial, please post on our dev forums (forums.couchbase.com) with relevant logs

Leave a reply