托管同步会话 - Node.js SDK
当您使用 Atlas Device Sync 时,Node.js SDK 使用同步会话在背景与 Atlas 同步数据。每当您打开同步 Realm 时,同步会话就会启动。
先决条件
在托管同步会话之前,您必须执行以下操作:
Access 同步会话
打开同步域后,您可以使用 Realm.syncSession属性访问权限其同步会话。
const realm = await Realm.open(config); const syncSession = realm.syncSession;
暂停或恢复同步会话
打开同步域会启动同步会话。 您可以暂停和恢复域上的同步会话。 暂停同步会话只会暂停该 Realm 的同步会话。 如果您有多个打开的域,暂停不会影响其他 Realm 的同步会话。
要暂停同步,请使用syncSession.pause() 方法。 要恢复同步,请使用syncSession.resume() 方法。
const behaviorConfiguration = { type: "openImmediately", }; const config = { schema: [DogSchema], sync: { user: app.currentUser, partitionValue: "MyPartitionValue", newRealmFileBehavior: behaviorConfiguration, existingRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config); const pauseSyncSession = () => { realm.syncSession?.pause(); }; const resumeSyncSession = () => { realm.syncSession?.resume(); };
const behaviorConfiguration: Realm.OpenRealmBehaviorConfiguration = { type: Realm.OpenRealmBehaviorType.OpenImmediately, }; const config: Realm.Configuration = { schema: [DogSchema], sync: { user: app.currentUser!, partitionValue: "MyPartitionValue", newRealmFileBehavior: behaviorConfiguration, existingRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config); const pauseSyncSession = () => { realm.syncSession?.pause(); }; const resumeSyncSession = () => { realm.syncSession?.resume(); };
何时暂停同步会话
对于大多数应用程序,无需手动暂停和恢复同步会话。 但是,在某些情况下,您可能希望暂停或暂停同步会话:
您只想在用户执行特定操作后进行同步
您只想在一天中的特定时间进行同步
您不想在网络连接较差时尝试同步
您想要显式强制同步会话连接
在网络连接较差的情况下,不断尝试建立网络连接可能会耗尽用户的设备电池。
显式强制同步会话连接的情况最常见与离线一段时间有关。同步客户端尝试连接,一旦失败,就会Go指数退避状态。长时间离线后,客户端可能无法立即重新连接。 暂停和恢复同步会话会显式强制连接。
当您暂停同步会话时,请记住以下事项:
暂停同步会话会使其在两个方向上暂停。您的应用在设备上所做的更改不会与后端同步,对后端或其他设备上的数据的更改也不会同步到设备。 无法仅暂停上传或仅暂停下载。
如果您希望客户端永久停止与后端同步,请勿暂停同步会话。 要永久停止同步,请将同步 Realm 的内容复制到非同步 Realm,并在客户端中使用该非同步 Realm。
请勿在不确定的时间段或以月和年为单位的时间范围内通过暂停同步来停止同步。 该功能不是针对这些使用案例而设计或测试的。 以这种方式使用时,您可能会遇到一系列问题。
等待上传和下载
要异步等待所有更改从同步域上传到Atlas ,请调用uploadAllLocalChanges() 。 当所有更改均已上传后,此方法将返回 true。
realm.write(() => { realm.create(Doggie, { _id: new BSON.ObjectID(), owner_id: app.currentUser!.id, name: "Maui", age: 3, }); }); await realm.syncSession?.uploadAllLocalChanges();
要异步等待 Atlas 上的所有更改从 Device Sync 服务器下载到同步 Realm,请调用downloadAllServerChanges() 。 下载所有更改后,此方法返回 true。
await realm.syncSession?.downloadAllServerChanges();
您可以在App 配置上指定请求超时时间。 指定超时后,您可以在BaseSyncConfiguration上设置 cancelWaitsOnNonFatalErrors
。 当true
和超时间隔到达时,等待上传和下载的任何未完成工作都会取消。 当此设置为 false 时,等待上传和下载不会取消,因为 Realm 将这些超时视为非致命错误。
有关详细信息,请参阅为应用程序客户端配置超时和超时后取消异步操作。
检查同步会话的上传和下载进度
要检查同步会话的上传和下载进度,请使用syncSession.addProgressNotification()添加进度通知 方法。
syncSession.addProgressNotification()
方法接受以下三个参数:
一个
direction
参数。 设置为"upload"
以注册上传数据的通知。 设置为"download"
以注册下载数据的通知。一个
mode
参数。 设置为"reportIndefinitely"
以使通知继续,直到使用syncSession.removeProgressNotification()取消注册回调为止。 设置为"forCurrentlyOutstandingWork"
以使通知继续,直到仅同步当前可传输的字节。回调函数参数,其参数为
transferred
和transferable
。transferred
是当前已传输的字节数。transferable
是已传输的字节总数加上待传输的字节数。
注意
尚不完全支持 Flexible Sync 进度通知。 使用Flexible Sync时,仅在集成更改后下载报告通知。 基于分区的同步在下载变更时提供持续通知。 上传报告两种同步模式的持续进度通知。
例子
在以下示例中,应用程序开发者在syncSession
上注册回调以无限期地侦听上传事件。 开发者写入到域,然后取消注册syncSession
通知回调。
const behaviorConfiguration = { type: "openImmediately", }; const config = { schema: [DogSchema], sync: { user: app.currentUser, partitionValue: "MyPartitionValue", newRealmFileBehavior: behaviorConfiguration, existingRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config); const handleNotifcationRemoval = (transferred, transferable) => { console.log(`There were ${transferable} transferable bytes total.`); console.log(`${transferred} bytes were transferred.`); }; const handleNotifications = (transferred, transferable) => { if (transferred === transferable) { console.log( `${transferred} bytes of ${transferable} were transferred.` ); // Remove progress notification. realm.syncSession?.removeProgressNotification(handleNotifcationRemoval); } }; realm.syncSession?.addProgressNotification( "upload", "reportIndefinitely", handleNotifications ); // Upload a Realm object. const dog = realm.write(() => { return realm.create("Dog", { _id: new Realm.BSON.ObjectID(), MyPartitionValue: "MyPartitionValue", name: "Fido", age: 2, }); });
const behaviorConfiguration: Realm.OpenRealmBehaviorConfiguration = { type: Realm.OpenRealmBehaviorType.OpenImmediately, }; const config: Realm.Configuration = { schema: [DogSchema], sync: { user: app.currentUser!, partitionValue: "MyPartitionValue", newRealmFileBehavior: behaviorConfiguration, existingRealmFileBehavior: behaviorConfiguration, }, }; const realm = await Realm.open(config); const handleNotifcationRemoval = ( transferred: number, transferable: number ) => { console.log(`There were ${transferable} transferable bytes total.`); console.log(`${transferred} bytes were transferred.`); }; const handleNotifications = (transferred: number, transferable: number) => { if (transferred === transferable) { console.log( `${transferred} bytes of ${transferable} were transferred.` ); // Remove progress notification. realm.syncSession?.removeProgressNotification(handleNotifcationRemoval); } }; realm.syncSession?.addProgressNotification( Realm.ProgressDirection.Upload, Realm.ProgressMode.ReportIndefinitely, handleNotifications ); // Upload a Realm object. const dog = realm.write(() => { return realm.create("Dog", { _id: new Realm.BSON.ObjectID(), MyPartitionValue: "MyPartitionValue", name: "Fido", age: 2, }); });
检查网络连接
要检查与服务器连接的当前状态,请调用syncSession.connectionState() 方法。
Realm 的离线优先设计意味着您通常不需要检查当前的网络连接状态。 也就是说,如果您的应用需要获取服务器连接的当前状态,则可以使用syncSession.connectionState()
方法。
const config = { schema: [DogSchema], sync: { user: app.currentUser, partitionValue: "MyPartitionValue", }, }; const realm = await Realm.open(config); const connectionState = realm.syncSession?.connectionState;
const config: Realm.Configuration = { schema: [DogSchema], sync: { user: app.currentUser!, partitionValue: "MyPartitionValue", }, }; const realm = await Realm.open(config); const connectionState = realm.syncSession?.connectionState;
多路复用同步会话
启用 会话多路复用 来整合Realm应用的多个同步会话。仅当看到有关达到文件限制的错误,并且知道正在使用许多同步会话时,才使用会话多路复用。
要启用会话多路复用,请调用Realm.App.Sync.enableSessionMultiplexing() 与您的Realm.App 一起使用。
例子
Realm.App.Sync.enableSessionMultiplexing(app);