The Discover Couchbase section continues with the fifth chapter, which deals in particular with Peer-to-Peer Sync.

In the previous article we discovered how to make an app using the Couchbase Sync Gateway and how to replicate data by a remote Database sync. Today we are going to discover how to replicate data with a Peer-to-Peer approach, using a specific feature of the Enterprise edition of Couchbase Lite called Peer-to-Peer Sync.

Why should I opt for Peer-to-Peer Sync?

Peer-to-Peer (P2P) is an application architecture where all elements involved are peers and don’t have hierarchy among them. In our case that means that every Peer can act as client and server by itself as necessary.

Moreover, the communication via Peer-to-Peer does not require any internet connection. So it can be particularly useful in areas lacking of internet connection, zone with low connectivity, or maybe if you just want to avoid the net for any reason. 

On the other hand this technology needs that all involved devices have to be relatively close one to each other. In fact to communicate  peer devices can use: 

  • Bluetooth which has a short connectivity range;
  • Wi-Fi-Direct that requires all the devices are connected to the same Wi-Fi network.

Multipeer Connectivity Framework

Couchbase provides the SDK to use its replication system, but is up to the developer to handle the communication between peers. In fact, to deal with Peer-to-Peer connectivity and communication Couchbase suggest to use the Multipeer Connectivity Framework (for iOS platform).
This framework makes us able to discover nearby devices and ask for connection.

After that, it begins the authentication phase, when the two peers can authorize the connection by a custom protocol.

Once connected, we are free to communicate with other peers.

Establishing a connection

The main characters here are:

  • MCNearbyServiceAdvertiser: something like a broadcaster, it publishes the service that will be searched by the browser. Moreover It provides some info to ease the discovery;
  • MCNearbyServiceBrowser: the Advertiser’s service detector. It searches for services offered by nearby devices using infrastructure Wi-Fi, peer-to-peer Wi-Fi, and Bluetooth (in iOS) or Ethernet (in macOS and tvOS). It provides the ability to easily invite those devices to a Multipeer Connectivity session.

Once the browser detects the service it can start the connection between the two devices.

Sending and receiving data

After establishing the connection, the session starts.
The session handles device connection and communication, as a matter of fact we can send data thanks to its method func send(_:toPeers:with:), and through its delegate methods func session(MCSession, didReceive: Data, fromPeer: MCPeerID) we are able to detect the received data.

In fact, when the data are sent using the method above, the MCSessionDelegate will trigger the didReceive method.
At this point the data received, you can manage it as you want.

Couchbase Peer-to-Peer Sync

The keypoint of the Couchbase Peer-to-Peer Sync feature is the automatic replication among different databases. This Couchbase feature is a layer of abstraction above the communication framework, which takes care about storing sent or received data.

Main characters of Peer-to-Peer Sync

The main characters involved in this feature are:

ActivePeer and PassivePeer

Couchbase splits peer behaviour in ActivePeer and PassivePeer.
The ActivePeer is the Peer who starts the connection and which sends data. Something like a client.
The PassivePeer is the peer who accepts the connection and which receives data, unlike the ActivePeer it acts as a server.
However ActivePeer and PassivePeer are different sides of the same Peer. Sometimes we need an ActivePeer, sometimes we could need a PassivePeer.

ActivePeerPassivePeer
DatabaseDatabase
ReplicatorMessageEndpointListener
MessageEndpointConnectionMessageEndpointConnection

As we can see from the table above, the main difference between the two Peers is that ActivePeer is associated to the Replicator, and the PassivePeer is associated to the MessageEndpointListener. As a matter of fact the PassivePeer is just meant to “listen” to changes coming from the ActivePeer (which started the replication process) and to replicate them.

Sending data with Peer-to-Peer Sync

As we said during the introduction Couchbase Peer-to-Peer Sync feature is an abstraction above a communication framework. This means that we have to handle by our own the communication between peers.

In fact the MessageEndpointConnection is a protocol we must implement to communicate with other peers.

For sending data to other devices we need to implement this method:

func send(message: Message, completion: @escaping (Bool, MessagingError?) -> Void)

In our case we use the MultipeerConnectivity Framework so the implementation will be something like this.

func send(message: Message, completion: @escaping (Bool, MessagingError?) -> Void) {
  do {
    try multiPeerManager.session.send(message.toData(), toPeers: 
    multiPeerManager.session.connectedPeers, with: .reliable)
  } catch {
    // handle error
  }
}

The method we just implemented will be automatically triggered as soon as we store our data in the Database. Now we just have to implement this method and store some data to start the replication.

Receiving Data with Peer-to-Peer Sync

As we just did for the data sending, we need also to enable the communication framework to receive data. In this case the SessionDelegate will pass the data to ReplicatorConnection to complete the replication.

func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
replicatiorConnection.receive(message: Message.fromData(data))
}

Demonstration of Peer-to-Peer Sync

As a practical demonstration of this technology, we made a simple chat app integrating the Couchbase Peer-to-Peer Sync SDK. We used Multipeer Connectivity Framework to handle the communication and Couchbase Lite to store chat messages. We use replication to actually send messages to the other device. to actually send the messages to the other device.

Couchbase Peer to Peer Sync – Demonstration

This clearly illustratets that the two devices act as ActivePeer when they send the message and as PassivePeer when they receive it.
When the send button is pressed the message is stored in the ActivePeer DB. Thanks to the Peer-to-Peer Sync solution, replication is automatically sent to the PassivePeer. The method 

func session(MCSession, didReceive: Data, fromPeer: MCPeerID)

is triggered and the 

replicatiorConnection.receive(message: Message.fromData(data))

tells to PassivePeer to accept the incoming data, to parse them and to store them in the local database.

I hope you enjoyed the reading about Couchbase Peer-to-Peer Sync. Stay tuned for more!
If you missed the articles in the Discover Couchbase with MOLO17 section, click here to read the series.