Adding Sync

In this lesson you’ll be introduced to Sync Gateway, our secure web gateway. You’ll learn how to use Couchbase Lite’s synchronization APIs, set up Sync Gateway for synchronization with the cloud and other devices, and resolve data conflicts within your application.

Requirements

Xcode 8 (Swift 3)

Getting Started

Download the project below.

Unzip the file and install Couchbase Lite using the install script.

$ cd xcode-project
$ ./install.sh

Open Todo.xcodeproj in Xcode. Then build & run the project.

Requirements

Visual Studio 2015+ (Windows) or Xamarin Studio 6+ (OS X)

Getting Started

Download the project below.

Requirements

Android Studio 2.2

Android SDK 24

Android Build Tools 24.0.3

JDK 8

⚠️ Docker and x86 Android emulators are not compatible (i.e cannot run simultaneously on the same machine). Make sure Docker isn't running in the background when deploying the application to an x86 Android emulator.

Getting Started

Download the project below.

Tip: To make things a bit more exciting, you may want to use the pre-built database containing a list of Groceries. Refer to the Create a Database lesson to learn how to use it.

Install Sync Gateway

Now that your application runs smoothly on the device you are ready to introduce Sync Gateway. Create a new file called sync-gateway-config.json with the following.

During development, you can set the server property to walrus: (also known as the Walrus mode) and it will keep the data in memory. Note that anytime you restart Sync Gateway in walrus mode, the database will be empty.

By default, Sync Gateway doesn't allow unauthenticated requests to be processed for security reasons. So you're enabling the GUEST user which represents all the unauthenticated clients that will be synchronizing with your Sync Gateway instance.

Note: User authentication is covered in more detail in the Adding Security lesson.

Sync Gateway is always listening on two ports:

4984: the public port which will be used from the application.

4985: the admin port used for administrative tasks (for security reasons, it’s only accessible on localhost).

Note: The Sync Gateway service might be running on Windows which will prevent this command from succeeding with the message 'FATAL: Failed to start HTTP server on 127.0.0.1:4985: listen tcp 127.0.0.1:4985: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.' To get around this, stop the 'Couchbase Sync Gateway' service in 'services.msc'.

Add synchronization

Typically, an application needs to send data to the server and receive it. In Couchbase Mobile, this is handled by replications which run on the device. A replication requires a Couchbase Lite database and a Sync Gateway URL, and synchronizes data between the two. They can be of two types:

Push: The data is pushed from Couchbase Lite to Sync Gateway.

Pull: The data is pulled from Sync Gateway to Couchbase Lite.

There are a few terminologies that designate the role of each database involved in a replications:

Source: The database where the data is read.

Target: The database where the data is written.

Local: The database that resides where the replication is running.

Remote: The database to which the replication is sending data.

The following code starts a pull and push replication with progress notifications.

Open http://localhost:4985/_admin/db/todo in the browser and notice that all the documents are pushed to Sync Gateway! You may have more or less rows depending on how many documents are present in the Couchbase Lite database.

Open http://localhost:4985/_admin/db/todo in the browser and notice that all the documents are pushed to Sync Gateway! You may have more or less rows depending on how many documents are present in the Couchbase Lite database.

Open http://localhost:4985/_admin/db/todo in the browser and notice that all the documents are pushed to Sync Gateway! You may have more or less rows depending on how many documents are present in the Couchbase Lite database.

Resolve Conflicts

Due to the unpredictability of mobile connections it's inevitable that more than one device will update the same document simultaneously. Couchbase Lite provides features to resolve these conflicts. The resolution rules are written by the developer to keep full control over which revision should be picked. The most common resolution methods are:

Deletes always win: if one side deletes a document it will always stay deleted, even if the other side has made changes to it later on.

N-way merge: if both sides have updated different properties, the document will end up with the updates from both sides.

Last update wins: if both sides have updated the same property, the value will end up as the last one that was updated.

Revisions form a tree data structure and a conflict occurs when there are multiple branches in the revision tree. On the diagram below the conflict is resolved by deleting one branch of the tree (the branch starting at 3-42cc). The other one is the active branch (i.e the winner) where further child revisions can be persisted (4-45cb and 5-42bb).

Detecting conflicts

To resolve conflicts you must first learn how to detect them. The code below uses an All Docs query which is an index of all the documents in the local database. The OnlyConflicts option is passed to report only the documents with conflicts and a LiveQuery is used to continuously monitor the database for changes.

The query results are then posted to the application code using the change callback or change listener.

Automatic conflict resolution

Even if the conflict isn’t resolved, Couchbase Lite has to return something. It chooses one of the two conflicting revisions as the "winner". The choice is deterministic, which means that every device that is faced with the same conflict will pick the same winner, without having to communicate.

Shown below is a list document created with two conflicting revisions. After deleting the row, the text Text Changed appears which is the name of the second conflicting revision. The action of deleting a document only deletes the current revision and if there are conflicting revisions it will be promoted as the new current revision.

Note: During development, the method saveAllowingConflicts is used to intentionally create a conflict. You can shake the device (^⌘Z on the simulator) to create a list conflict. The code is located in the motionEnded(_:with:) method of ListsViewController.swift.

Note: During development, the method Save(bool) is used to intentionally create a conflict. You can press Ctrl+C to create a list conflict. The code is located in the TestConflict() method of TaskListsModel.cs.

iOSAndroid

Note: During development, the method save(boolean) is used to intentionally create a conflict. You can long press the floating action button to create a list conflict. The code is located in the createListConflict() method of ListsActivity.java.

This can be surprising at first but it’s the strength of using a distributed database that defers the conflict resolution logic to the application. It’s your responsibility as the developer to ensure conflicts are resolved! Even if you decide to let Couchbase Lite pick the winner you must remove extraneous conflicting revisions to prevent the behaviour observed above. The code below removes all revisions except the current/winning one.

Perform the same actions and this time deleting the list conflict doesn’t reveal the subsequent conflicting revision anymore.

iOSAndroid

To enable conflict resolution, set the mConflictResolution constant in Application.java to true.

private Boolean mConflictResolution = true;

Perform the same actions and this time deleting the list conflict doesn't reveal the subsequent conflicting revision anymore.

N-way conflict resolution

For task documents, you will follow the same steps as previously except this time the conflict resolution will merge the differences between the conflicting revisions into a new revision before removing them. This time, one revision changes the title of the task while the other revision marks it as completed.

Note: To see the same result, open any list and shake the device (^⌘Z on the simulator) to create a task conflict. The code is located in the motionEnded(_:with:) method of TasksViewController.swift. Be sure to disable conflict resolution to see the same result as the animation above.

Note: To see the same result, open any list and press Ctrl+C to create a task conflict. The code is located in the TestConflict() method of TasksModel.cs. Be sure to disable conflict resolution to see the same result as the animation above.

Note: To see the same result, open any list and long press the floating action button to create a task conflict. The code is located in the createTaskConflict() method of TasksFragment.java. Be sure to disable conflict resolution to see the same result as the animation above.

Similarly to the previous section, you will learn how to resolve conflicts, this time for "task" documents. In this case, the resolution code will merge the changes (i.e n-way merge) of the conflicting revisions and promote the result as the current revision.

Notice that for 'task' documents, the nWayMergeConflicts() method is called to merge the differences of conflicting revisions. The body of this method is too long to copy here but you can find it in the same file.

Try it out

Enable conflict resolution.

let kConflictResolution = true

Build and run.

Create a task conflict using the shake gesture (or ^⌘Z) and this time the row contains the updated text and is marked as completed.

Create a task conflict using the shake gesture and this time the row contains the updated text and is marked as completed.

iOSAndroid

Enable conflict resolution in Application.java.

private Boolean mConflictResolution = true;

Build and run.

Create a task conflict using the shake gesture and this time the row contains the updated text and is marked as completed.

Conclusion

Well done! You've completed this lesson on enabling synchronization, detecting and resolving conflicts. In the next lesson you'll learn how to implement authentication and define access control rules in the Sync Function. Feel free to share your feedback, findings or ask any questions on the forums.