|
| 1 | + |
1 | 2 | = Integrate a Custom Built Listener
|
2 | 3 | :page-aliases: learn/java-android-p2psync-custom.adoc
|
3 | 4 | ifdef::show_edition[:page-edition: {release}] {enterprise}
|
4 |
| -ifdef::prerelease[:page-status: {prerelease}] |
5 | 5 | :page-role:
|
6 | 6 | :description: Couchbase Lite database peer-to-peer sync- integrate a custom built listener
|
7 | 7 |
|
8 | 8 |
|
9 |
| -include::partial$_set_page_context_for_android.adoc[] |
10 |
| -// :param-name: {lang-name-android} |
11 |
| -// :param-title: {lang-title-android} |
12 |
| -// :param-module: {lang-mod-android} |
13 |
| -:topic-group: Using Peer-to-Peer Synchronization (custom) |
14 |
| -:param-related: {url-api-references}[API Reference] | {p2psync-websocket--xref} | {p2psync-custom--xref} |
| 9 | +:source-language: Java |
| 10 | + |
| 11 | + |
| 12 | +:source-language: Kotlin |
| 13 | + |
| 14 | + |
| 15 | +// :param-name: kotlin |
| 16 | +// :param-title: Android |
| 17 | +// :param-module: android |
| 18 | + |
| 19 | + |
| 20 | +[abstract] |
| 21 | +-- |
| 22 | +Description -- _{description}_ + |
| 23 | +Related Content -- https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-android}{empty}/couchbase-lite-android/[API Reference] | xref:android:p2psync-websocket.adoc[Peer-to-Peer] | xref:android:p2psync-custom.adoc[Integrate Custom Listener] |
| 24 | +-- |
| 25 | + |
| 26 | +[#overview] |
| 27 | +== Overview |
| 28 | + |
| 29 | +.Enterprise Edition only |
| 30 | +IMPORTANT: Peer-to-Peer Synchronization is an https://www.couchbase.com/products/editions[Enterprise Edition] feature. |
| 31 | +You must purchase the Enterprise License, which includes official https://www.couchbase.com/support-policy[Couchbase Support]. |
| 32 | +To use it in production (also see the https://www.couchbase.com/licensing-and-support-faq[FAQ]). |
| 33 | + |
| 34 | +This content covers how to integrate a custom __MessageEndpointListener__ solution with Couchbase Lite to handle the data transfer, which is the sending and receiving of data. |
| 35 | +Where applicable, we discuss how to integrate Couchbase Lite into the workflow. |
| 36 | + |
| 37 | +The following sections describe a typical Peer-to-Peer workflow. |
| 38 | + |
| 39 | +[#peer-discovery] |
| 40 | +== Peer Discovery |
| 41 | + |
| 42 | +Peer discovery is the first step. |
| 43 | +The communication framework will generally include a Peer discovery API for devices to advertise themselves on the network and to browse for other Peers. |
| 44 | + |
| 45 | +image::ROOT:discovery.png[] |
| 46 | + |
| 47 | +[#active-peer] |
| 48 | +=== Active Peer |
| 49 | + |
| 50 | +The first step is to initialize the Couchbase Lite database. |
| 51 | + |
| 52 | +[#passive-peer] |
| 53 | +=== Passive Peer |
| 54 | + |
| 55 | +In addition to initializing the database, the Passive Peer must initialize the `MessageEndpointListener`. |
| 56 | +The `MessageEndpointListener` acts as a Listener for incoming connections. |
| 57 | + |
| 58 | +[source] |
| 59 | +---- |
| 60 | +include::android:example$codesnippet_collection.kt[tag=listener,indent=0] |
| 61 | +---- |
| 62 | + |
| 63 | +[#peer-selection-and-connection-setup] |
| 64 | +== Peer Selection and Connection Setup |
| 65 | + |
| 66 | + |
| 67 | +Once a Peer device is found, the application code must decide whether it should establish a connection with that Peer. |
| 68 | +This step includes inviting a Peer to a session and Peer authentication. |
| 69 | + |
| 70 | +This is handled by the Communication Framework. |
| 71 | + |
| 72 | +image::ROOT:selection.png[] |
| 73 | + |
| 74 | +Once the remote Peer has been authenticated, the next step is to connect with that Peer and initialize the Message Endpoint API. |
| 75 | + |
| 76 | + |
| 77 | +[#replication-setup] |
| 78 | +== Replication Setup |
| 79 | + |
| 80 | + |
| 81 | +image::ROOT:connection.png[] |
| 82 | + |
| 83 | +[#active-peer-2] |
| 84 | +=== Active Peer |
| 85 | + |
| 86 | +When the connection is established, the active Peer must instantiate a `MessageEndpoint` object corresponding to the remote Peer. |
| 87 | + |
| 88 | +[source] |
| 89 | +---- |
| 90 | +include::android:example$codesnippet_collection.kt[tag=message-endpoint,indent=0] |
| 91 | +---- |
| 92 | + |
| 93 | +The `MessageEndpoint` initializer takes the following arguments. |
| 94 | + |
| 95 | +. `uid`: a unique ID that represents the remote active Peer. |
| 96 | +. `target`: This represents the remote passive Peer and could be any suitable representation of the remote Peer. |
| 97 | +It could be an Id, URL etc. |
| 98 | +If using the MultiPeerConnectivity Framework, this could be the MCPeerID. |
| 99 | +. `protocolType`: specifies the kind of transport you intend to implement. |
| 100 | +There are two options. |
| 101 | + ** The default (`MessageStream`) means that you want to "send a series of messages", or in other words the Communication Framework will control the formatting of messages so that there are clear boundaries between messages. |
| 102 | + ** The alternative (`ByteStream`) means that you just want to send raw bytes over the stream and Couchbase should format for you to ensure that messages get delivered in full. |
| 103 | ++ |
| 104 | +Typically, the Communication Framework will handle message assembly and disassembly so you would use the `MessageType` option in most cases. |
| 105 | + |
| 106 | +. `delegate`: the delegate that will implement the `MessageEndpointDelegate` protocol, which is a factory for `MessageEndpointConnection`. |
| 107 | + |
| 108 | +Then, a `Replicator` is instantiated with the initialized `MessageEndpoint` as the target. |
| 109 | + |
| 110 | +[source] |
| 111 | +---- |
| 112 | +include::android:example$codesnippet_collection.kt[tag=message-endpoint-replicator,indent=0] |
| 113 | +---- |
| 114 | + |
| 115 | +Next, Couchbase Lite will call back the application code through the `MessageEndpointDelegate.createConnection` interface method. |
| 116 | +When the application receives the callback, it must create an instance of `MessageEndpointConnection` and return it. |
| 117 | + |
| 118 | + |
| 119 | +[source] |
| 120 | +---- |
| 121 | +include::android:example$codesnippet_collection.kt[tag=create-connection,indent=0] |
| 122 | +---- |
| 123 | +Next, Couchbase Lite will call back the application code through the `MessageEndpointConnection.open` method. |
| 124 | + |
| 125 | +[source] |
| 126 | +---- |
| 127 | +include::android:example$codesnippet_collection.kt[tag=active-peer-open,indent=0] |
| 128 | +---- |
| 129 | + |
| 130 | +The connection argument is then set on an instance variable. |
| 131 | +The application code must keep track of every `ReplicatorConnection` associated with every `MessageEndpointConnection`. |
| 132 | + |
| 133 | +The `MessageError` argument in the completion block specifies whether the error is recoverable or not. |
| 134 | +If it is a recoverable error, the replicator will begin a retry process, creating a new `MessageEndpointConnection` instance. |
| 135 | + |
| 136 | +[#passive-peer-2] |
| 137 | +=== Passive Peer |
| 138 | + |
| 139 | +After connection establishment on the Passive Peer, the first step is to initialize a new `MessageEndpointConnection` and pass it to the listener. |
| 140 | +This message tells the listener to accept incoming data from that Peer. |
| 141 | + |
| 142 | +[source] |
| 143 | +---- |
| 144 | +include::android:example$codesnippet_collection.kt[tag=advertizer-accept,indent=0] |
| 145 | +---- |
| 146 | + |
| 147 | +`messageEndpointListener` is the instance of the `MessageEndpointListener` that was created in the first step (<<peer-discovery,Peer Discovery>>) |
| 148 | + |
| 149 | +Couchbase Lite will call the application code back through the `MessageEndpointConnection.open` method. |
| 150 | + |
| 151 | +[source] |
| 152 | +---- |
| 153 | +include::android:example$codesnippet_collection.kt[tag=passive-peer-open,indent=0] |
| 154 | +---- |
| 155 | + |
| 156 | +The `connection` argument is then set on an instance variable. |
| 157 | +The application code must keep track of every `ReplicatorConnection` associated with every `MessageEndpointConnection`. |
| 158 | + |
| 159 | +At this point, the connection is established, and both Peers are ready to exchange data. |
| 160 | + |
| 161 | + |
| 162 | +[#pushpull-replication] |
| 163 | +== Push/Pull Replication |
| 164 | + |
| 165 | +Typically, an application needs to send data and receive data. |
| 166 | +The directionality of the replication could be any of the following. |
| 167 | + |
| 168 | +* *Push only:* The data is pushed from the local database to the remote database. |
| 169 | + |
| 170 | +* *Pull only:* The data is pulled from the remote database to the local database. |
| 171 | + |
| 172 | +* *Push and Pull:* The data is exchanged both ways. |
| 173 | + |
| 174 | +Usually, the remote is a Sync Gateway database identified through a URL. |
| 175 | +In Peer-to-Peer syncing, the remote is another Couchbase Lite database. |
| 176 | + |
| 177 | +image::ROOT:replication.png[] |
| 178 | + |
| 179 | +The replication lifecycle is handled through the `MessageEndpointConnection`. |
| 180 | + |
| 181 | +[#active-peer-3] |
| 182 | +=== Active Peer |
| 183 | + |
| 184 | +When Couchbase Lite calls back the application code through the `MessageEndpointConnection.send` method, you should send that data to the other Peer using the communication framework. |
| 185 | + |
| 186 | +[source] |
| 187 | +---- |
| 188 | +include::android:example$codesnippet_collection.kt[tag=active-peer-send,indent=0] |
| 189 | +---- |
| 190 | + |
| 191 | +Once the data is sent, call the completion block to acknowledge the completion. |
| 192 | +You can use the `MessageError` in the completion block to specify whether the error is recoverable. |
| 193 | +If it is a recoverable error, the replicator will begin a retry process, creating a new `MessageEndpointConnection`. |
| 194 | + |
| 195 | + |
| 196 | +When data is received from the passive Peer via the Communication Framework, you call the `ReplicatorConnection.receive` method. |
| 197 | + |
| 198 | +[source] |
| 199 | +---- |
| 200 | +include::android:example$codesnippet_collection.kt[tag=active-peer-receive,indent=0] |
| 201 | +---- |
| 202 | + |
| 203 | +The replication connection's `receive` method is called. Which then processes the data to persist to the local database. |
| 204 | + |
| 205 | +[#passive-peer-3] |
| 206 | +=== Passive Peer |
| 207 | + |
| 208 | +As in the case of the active Peer, the passive Peer must implement the `MessageEndpointConnection.send` method to send data to the other Peer. |
| 209 | + |
| 210 | +[source] |
| 211 | +---- |
| 212 | +include::android:example$codesnippet_collection.kt[tag=passive-peer-send,indent=0] |
| 213 | +---- |
| 214 | + |
| 215 | +Once the data is sent, call the completion block to acknowledge the completion. |
| 216 | +You can use the `MessageError` in the completion block to specify whether the error is recoverable. |
| 217 | +If it is a recoverable error, the replicator will begin a retry process, creating a new `MessageEndpointConnection`. |
| 218 | + |
| 219 | +When data is received from the active Peer via the Communication Framework, you call the `ReplicatorConnection.receive` method. |
| 220 | + |
| 221 | +[source] |
| 222 | +---- |
| 223 | +include::android:example$codesnippet_collection.kt[tag=passive-peer-receive,indent=0] |
| 224 | +---- |
| 225 | + |
| 226 | +[#connection-teardown] |
| 227 | +== Connection Teardown |
| 228 | + |
| 229 | +When a Peer disconnects from a Peer-to-Peer network, all connected Peers are notified. |
| 230 | +The disconnect notification is a good opportunity to close and remove a replication connection. |
| 231 | +The steps to Teardown the connection are slightly different depending on whether the active or passive Peer disconnects first. |
| 232 | +We will cover each case below. |
| 233 | + |
| 234 | +[#initiated-by-active-peer] |
| 235 | +=== Initiated by Active Peer |
| 236 | + |
| 237 | +image::ROOT:dis-active.png[] |
| 238 | + |
| 239 | +[#active-peer-4] |
| 240 | +=== Active Peer |
| 241 | + |
| 242 | +When an active Peer disconnects, it must call the `ReplicatorConnection.close` method. |
| 243 | + |
| 244 | +[source] |
| 245 | +---- |
| 246 | +include::android:example$codesnippet_collection.kt[tag=active-replicator-close,indent=0] |
| 247 | +---- |
| 248 | + |
| 249 | +Then, Couchbase Lite will call back your code through the `MessageEndpointConnection.close` to allow the application to disconnect with the Communication Framework. |
| 250 | + |
| 251 | +[source] |
| 252 | +---- |
| 253 | +include::android:example$codesnippet_collection.kt[tag=active-peer-close,indent=0] |
| 254 | +---- |
| 255 | + |
| 256 | +[#passive-peer-4] |
| 257 | +=== Passive Peer |
| 258 | + |
| 259 | +When the passive Peer receives the corresponding disconnect notification from the Communication Framework, it must call the `ReplicatorConnection.close` method. |
| 260 | + |
| 261 | +[source] |
| 262 | +---- |
| 263 | +include::android:example$codesnippet_collection.kt[tag=passive-replicator-close,indent=0] |
| 264 | +---- |
| 265 | + |
| 266 | +Then, Couchbase Lite will call back your code through the `MessageEndpointConnection.close` to allow the application to disconnect with the Communication Framework. |
| 267 | + |
| 268 | +[source] |
| 269 | +---- |
| 270 | +include::android:example$codesnippet_collection.kt[tag=passive-peer-close,indent=0] |
| 271 | +---- |
| 272 | + |
| 273 | +[#initiated-by-passive-peer] |
| 274 | +=== Initiated by Passive Peer |
| 275 | + |
| 276 | +image::ROOT:dis-passive.png[] |
| 277 | + |
| 278 | +[#passive-peer-5] |
| 279 | +=== Passive Peer |
| 280 | + |
| 281 | +When the passive disconnects, it must class the `MessageEndpointListener.closeAll` method. |
| 282 | + |
| 283 | +[source] |
| 284 | +---- |
| 285 | +include::android:example$codesnippet_collection.kt[tag=passive-stop-listener,indent=0] |
| 286 | +---- |
| 287 | + |
| 288 | +Then, Couchbase Lite will call back your code through the `MessageEndpointConnection.close` to allow the application to disconnect with the Communication Framework. |
| 289 | + |
| 290 | +[source] |
| 291 | +---- |
| 292 | +include::android:example$codesnippet_collection.kt[tag=passive-peer-close,indent=0] |
| 293 | +---- |
| 294 | + |
| 295 | +[#active-peer-5] |
| 296 | +=== Active Peer |
| 297 | + |
| 298 | +When the active Peer receives the corresponding disconnect notification from the Communication Framework, it must call the `ReplicatorConnection.close` method. |
| 299 | + |
| 300 | +[source] |
| 301 | +---- |
| 302 | +include::android:example$codesnippet_collection.kt[tag=active-replicator-close,indent=0] |
| 303 | +---- |
| 304 | + |
| 305 | +Then, Couchbase Lite will call back your code through the `MessageEndpointConnection.close` to allow the application to disconnect with the Communication Framework. |
| 306 | + |
| 307 | +[source] |
| 308 | +---- |
| 309 | +include::android:example$codesnippet_collection.kt[tag=active-peer-close,indent=0] |
| 310 | +---- |
| 311 | + |
| 312 | +[#related-content] |
| 313 | +== Related Content |
| 314 | +++++ |
| 315 | +<div class="card-row three-column-row"> |
| 316 | +++++ |
| 317 | + |
| 318 | +[.column] |
| 319 | +=== {empty} |
| 320 | +.How to |
| 321 | +* xref:android:p2psync-websocket-using-passive.adoc[Passive Peer] |
| 322 | +* xref:android:p2psync-websocket-using-active.adoc[Active Peer] |
| 323 | + |
| 324 | + |
| 325 | +. |
| 326 | + |
| 327 | +[.column] |
| 328 | +=== {empty} |
| 329 | +.Concepts |
| 330 | +* xref:android:landing-p2psync.adoc[Peer-to-Peer Sync] |
| 331 | + |
| 332 | +* https://docs.couchbase.com/mobile/{major}.{minor}.{maintenance-android}{empty}/couchbase-lite-android/[API References] |
| 333 | + |
| 334 | +. |
| 335 | + |
| 336 | + |
| 337 | +[.column] |
| 338 | +=== {empty} |
| 339 | +.Community Resources ... |
| 340 | +https://forums.couchbase.com/c/mobile/14[Mobile Forum] | |
| 341 | +https://blog.couchbase.com/[Blog] | |
| 342 | +https://docs.couchbase.com/tutorials/[Tutorials] |
| 343 | + |
| 344 | +. |
| 345 | +xref:tutorials:cbl-p2p-sync-websockets:swift/cbl-p2p-sync-websockets.adoc[Getting Started with Peer-to-Peer Synchronization] |
| 346 | + |
15 | 347 |
|
| 348 | +++++ |
| 349 | +</div> |
| 350 | +++++ |
16 | 351 |
|
17 |
| -include::{root-commons}p2psync-custom.adoc[subs="macros,attributes"] |
18 | 352 |
|
19 |
| -include::{root-partials}block-related-content-p2psync.adoc[] |
|
0 commit comments