1# Cross-Device Synchronization of Distributed Data Objects 2 3 4## When to Use 5 6To implement traditional data synchronization between devices, you need to design the message processing logic, including setting up a communication link, sending, receiving, and processing messages, retry mechanism upon errors, and resolving data conflicts. The workload is heavy. In addition, the debugging complexity increases with the number of devices. 7 8The device status, message sending progress, and data transmitted are variables. If these variables support global access, they can be accessed as local variables on difference devices. This simplifies data synchronization between multiple devices. 9 10The distributed data object (**DataObject**) implements global access to variables. **DataObject** provides basic data object management capabilities and distributed capabilities. You can use the APIs to create, query, delete, and modify in-memory objects and subscribe to event notifications. OpenHarmony also provides easy-to-use JS APIs for distributed application scenarios to easily implement cross-device data collaboration for the same application. In addition, object status and data changes on different devices can be observed. This feature implements data object collaboration for the same application between multiple devices that form a Super Device. **DataObject** greatly reduces the development workloads compared with the traditional mode. 11 12 13## Basic Concepts 14 15- Distributed in-memory database<br> 16 The distributed in-memory database caches data in the memory so that applications can quickly access data without persisting data. If the database is closed, the data is not retained. 17 18- Distributed data object 19 A distributed data object is an encapsulation of the JS object type. Each distributed data object instance creates a data table in the in-memory database. The in-memory databases created for different applications are isolated from each other. Reading data from and writing data to a distributed data object are mapped to the **get()** and **put()** operations in the corresponding database, respectively. 20 21 The distributed data object can be in the following states in its lifecycle: 22 23 - **Uninitialized**: The distributed data object is not instantiated or has been destroyed. 24 - **Local**: The data table is created, but the data cannot be synchronized. 25 - **Distributed**: The data table is created, and there are at least two online devices with the same session ID. In this case, data can be synchronized across devices. If a device is offline or the session ID is empty, the distributed data object changes to the local state. 26 27 28## Working Principles 29 30**Figure 1** Working mechanism 31 32![distributedObject](figures/distributedObject.jpg) 33 34The distributed data objects are encapsulated into JS objects in distributed in-memory databases. This allows the distributed data objects to be operated in the same way as local variables. The system automatically implements cross-device data synchronization. 35 36 37### JS Object Storage and Encapsulation Mechanism 38 39- An in-memory database is created for each distributed data object instance and identified by a session ID (**SessionId**). The in-memory databases created for different applications are isolated from each other. 40 41- When a distributed data object is instantiated, all properties of the object are traversed recursively. **Object.defineProperty** is used to define the **set()** and **get()** methods of all properties. The **set()** and **get()** methods correspond to the **put** and **get** operations of a record in the database, respectively. **Key** specifies the property name, and **Value** specifies the property value. 42 43- When a distributed data object is read or written, the **set()** and **get()** methods are automatically called to perform the related operations to the database. 44 45**Table 1** Correspondence between a distributed data object and a distributed database 46 47| Distributed Data Object Instance| Object Instance| Property Name| Property Value| 48| -------- | -------- | -------- | -------- | 49| Distributed in-memory database| Database identified by **sessionID**| Key of a record in the database| Value of a record in the database| 50 51 52### Cross-Device Synchronization and Data Change Notification Mechanism 53 54The distributed data object is used to implement data synchronization between objects. You can create a distributed data object and set **sessionID** for the devices on a trusted network. The distributed data objects with the same **sessionID** on different devices can synchronize data with each other. 55 56As shown in the following figure, distributed data object 1 on device A and device B have the same session ID **session1**. The synchronization relationship of session1 is established between the two objects. 57 58 **Figure 2** Object synchronization relationship 59 60![distributedObject_sync](figures/distributedObject_sync.jpg) 61 62For each device, only one object can be added to a synchronization relationship. As shown in the preceding figure, distributed data object 2 of device A cannot be added to session 1 because distributed data object 1 of device A has been added to session 1. 63 64After the synchronization relationship is established, each session has a copy of shared object data. The distributed data objects added to the same session support the following operations: 65 66 (1) Reading or modifying the data in the session. 67 68 (2) Listening for data changes made by other devices. 69 70 (3) Listening for status changes, such as the addition and removal of other devices. 71 72 73### Minimum Unit to Synchronize 74 75Attribute is the minimum unit to synchronize in distributed data objects. For example, object 1 in the following figure has three attributes: name, age, and parents. If one of the attributes is changed, only the changed attribute needs to be synchronized. 76 77**Figure 3** Synchronization of distributed data objects 78 79 80![distributedObject_syncView](figures/distributedObject_syncView.jpg) 81 82 83### Object Persistence Mechanism 84 85Distributed data objects run in the process space of applications. When the data of a distributed data object is persisted in the distributed database, the data will not be lost after the application exits. 86 87You need to persist distributed data objects in the following scenarios: 88 89- Enable an application to retrieve the exact same data after it is opened again. In this case, you need to persist the distributed data object (for example, object 1). After the application is opened again, create a distributed data object (for example, object 2) and set the session ID of object 1 for object 2. Then, the application can retrieve the data of object 1. 90 91- Enable an application opened on another device to retrieve the exact same data. In this case, you need to persist the distributed data object (for example, object 1) on device A and synchronize the data to device B. Then, create a distributed data object (for example, object 2) and set the session ID of object 1 for object 2. When the application is opened on device B, it can retrieve the same application data used on device A before the application is closed. 92 93 94## Constraints 95 96- Data synchronization can be implemented across devices only for the applications with the same **bundleName**. 97 98- Data can be synchronized only for the distributed data objects with the same **sessionID** of the same application. 99 100- Each distributed data object occupies 100 KB to 150 KB of memory. Therefore, you are advised not to create too many distributed data objects. 101 102- The maximum size of a distributed data object is 500 KB. 103 104- It takes about 50 ms from the time when 1 KB of data starts to be modified on a device to the time when another device receives a data change notification. 105 106- A maximum of 16 distributed data object instances can be created for an application. 107 108- For optimal performance and user experience, the maximum number of devices for data collaboration is 3. 109 110- For the distributed data object of the complex type, only the root attribute can be modified. The subordinate attributes cannot be modified. 111 112- Only JS APIs are supported. 113 114 115## Available APIs 116 117The following table lists the APIs for cross-device synchronization of distributed data objects. Most of the interfaces are executed asynchronously, using a callback or promise to return the result. The following table uses the callback-based APIs as an example. For more information about the APIs, see [Distributed Data Object](../reference/apis/js-apis-data-distributedobject.md). 118 119| API| Description| 120| -------- | -------- | 121| create(context: Context, source: object): DataObject | Creates a distributed data object instance.| 122| genSessionId(): string | Generates a session ID for distributed data objects.| 123| setSessionId(sessionId: string, callback: AsyncCallback<void>): void | Sets a session ID for data synchronization. Automatic synchronization is performed for devices with the same session ID on a trusted network.| 124| setSessionId(callback: AsyncCallback<void>): void | Exits all sessions.| 125| on(type: 'change', callback: Callback<{ sessionId: string, fields: Array<string> }>): void | Subscribes to data changes of this distributed data object.| 126| on(type: 'status', callback: Callback<{ sessionId: string, networkId: string, status: 'online' \| 'offline' }>): void | Subscribes to status changes of this distributed data object.| 127| save(deviceId: string, callback: AsyncCallback<SaveSuccessResponse>): void | Saves a distributed data object.| 128| revokeSave(callback: AsyncCallback<RevokeSaveSuccessResponse>): void | Revokes the save operation of the distributed data object.| 129 130 131## How to Develop 132 133The following example demonstrates how to implement a distributed data object synchronization. 134 1351. Import the **@ohos.data.distributedDataObject** module. 136 137 ```js 138 import distributedDataObject from '@ohos.data.distributedDataObject'; 139 ``` 140 1412. Request permissions. 142 143 1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). 144 2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). 145 1463. Creates a distributed data object instance. 147 148 Stage model: 149 150 ```js 151 // Import the module. 152 import distributedDataObject from '@ohos.data.distributedDataObject'; 153 import UIAbility from '@ohos.app.ability.UIAbility'; 154 155 class EntryAbility extends UIAbility { 156 onWindowStageCreate(windowStage) { 157 // Create a distributed data object, which contains attributes of the string, number, boolean, and object types. 158 let localObject = distributedDataObject.create(this.context, { 159 name: 'jack', 160 age: 18, 161 isVis: false, 162 parent: { mother: 'jack mom', father: 'jack Dad' }, 163 list: [{ mother: 'jack mom' }, { father: 'jack Dad' }] 164 }); 165 } 166 } 167 ``` 168 169 FA model: 170 171 172 ```js 173 // Import the module. 174 import distributedDataObject from '@ohos.data.distributedDataObject'; 175 import featureAbility from '@ohos.ability.featureAbility'; 176 // Obtain the context. 177 let context = featureAbility.getContext(); 178 // Create a distributed data object, which contains attributes of the string, number, boolean, and object types. 179 let localObject = distributedDataObject.create(context, { 180 name: 'jack', 181 age: 18, 182 isVis: false, 183 parent: { mother: 'jack mom', father: 'jack Dad' }, 184 list: [{ mother: 'jack mom' }, { father: 'jack Dad' }] 185 }); 186 ``` 187 1884. Set the same session ID for the distributed data objects for data synchronization. The data objects in the synchronization network include the local and remote objects. 189 190 ```js 191 // Set a session ID, for example, 123456, for device 1. 192 let sessionId = '123456'; 193 194 localObject.setSessionId(sessionId); 195 196 // Set the same session ID for device 2. 197 198 // Create a distributed data object, which contains attributes of the string, number, boolean, and object types. 199 let remoteObject = distributedDataObject.create(this.context, { 200 name: undefined, 201 age: undefined, // undefined indicates that the data comes from the peer end. 202 isVis: true, 203 parent: undefined, 204 list: undefined 205 }); 206 // After learning that the device goes online, the remote object synchronizes data. That is, name changes to jack and age to 18. 207 remoteObject.setSessionId(sessionId); 208 ``` 209 2105. Observe data changes of a distributed data object. You can subscribe to data changes of the remote object. When the data in the remote object changes, a callback will be invoked to return a data change event. 211 212 ```js 213 function changeCallback(sessionId, changeData) { 214 console.info(`change: ${sessionId}`); 215 216 if (changeData !== null && changeData !== undefined) { 217 changeData.forEach(element => { 218 console.info(`The element ${localObject[element]} changed.`); 219 }); 220 } 221 } 222 223 // To refresh the page in changeCallback, correctly bind (this) to the changeCallback. 224 localObject.on("change", this.changeCallback.bind(this)); 225 ``` 226 2276. Modify attributes of the distributed data object. The object attributes support basic data types (number, Boolean, and string) and complex data types (array and nested basic types). 228 229 ```js 230 localObject.name = 'jack1'; 231 localObject.age = 19; 232 localObject.isVis = false; 233 localObject.parent = { mother: 'jack1 mom', father: 'jack1 Dad' }; 234 localObject.list = [{ mother: 'jack1 mom' }, { father: 'jack1 Dad' }]; 235 ``` 236 237 > **NOTE** 238 > 239 > For the distributed data object of the complex type, only the root attribute can be modified. The subordinate attributes cannot be modified. 240 241 242 ```js 243 // Supported modification. 244 localObject.parent = { mother: 'mom', father: 'dad' }; 245 // Modification not supported. 246 localObject.parent.mother = 'mom'; 247 ``` 248 2497. Access a distributed data object. Obtain the distributed data object attributes, which are the latest data on the network. 250 251 ```js 252 console.info(`name:${localObject['name']}`); 253 ``` 254 2558. Unsubscribe from data changes. You can specify the callback to unregister. If you do not specify the callback, all data change callbacks of the distributed data object will be unregistered. 256 257 ```js 258 // Unregister this.changeCallback. 259 localObject.off('change', this.changeCallback); 260 // Unregister all data change callbacks. 261 localObject.off('change'); 262 ``` 263 2649. Subscribes to status changes of a distributed data object. A callback will be invoked to report the status change when the target distributed data object goes online or offline. 265 266 ```js 267 function statusCallback(sessionId, networkId, status) { 268 // Service processing. 269 } 270 271 localObject.on('status', this.statusCallback); 272 ``` 273 27410. Save a distributed data object and revoke the data saving operation. 275 276 ```js 277 // Save the data object if the device on the network needs to retrieve the object data after the application exits. 278 localObject.save('local').then((result) => { 279 console.info(`Succeeded in saving. SessionId:${result.sessionId},version:${result.version},deviceId:${result.deviceId}`); 280 }).catch((err) => { 281 console.error(`Failed to save. Code:${err.code},message:${err.message}`); 282 }); 283 284 // Revoke the save of a distributed data object. 285 localObject.revokeSave().then((result) => { 286 console.info(`Succeeded in revokeSaving. Session:${result.sessionId}`); 287 }).catch((err) => { 288 console.error(`Failed to revokeSave. Code:${err.code},message:${err.message}`); 289 }); 290 ``` 291 29211. Unsubscribe from the status changes of a distributed data object. You can specify the callback to unregister. If you do not specify the callback, this API unregisters all status change callbacks of this distributed data object. 293 294 ```js 295 // Unregister this.statusCallback. 296 localObject.off('status', this.statusCallback); 297 // Unregister all status change callbacks. 298 localObject.off('status'); 299 ``` 300 30112. Remove a distributed data object from the synchronization network. The data of the removed distributed data object will not be synchronized to other devices. 302 303 ```js 304 localObject.setSessionId(() => { 305 console.info('leave all lession.'); 306 }); 307 ``` 308