Docs Menu
Docs Home
/ /
Atlas Device SDKs
/ /

Manage a Sync Session - Node.js SDK

On this page

  • Prerequisites
  • Access Sync Session
  • Pause or Resume a Sync Session
  • When to Pause a Sync Session
  • Wait for Upload and Download
  • Check Upload & Download Progress for a Sync Session
  • Check the Network Connection
  • Multiplex Sync Sessions

When you use Atlas Device Sync, the Node.js SDK syncs data with Atlas in the background using a sync session. A sync session starts whenever you open a synced realm.

Before you can manage a sync session, you must perform the following:

  1. Open a synced realm

  2. Add a sync subscription

After opening a synced realm, you can access its sync session with the Realm.syncSession property.

const realm = await Realm.open(config);
const syncSession = realm.syncSession;

Opening a synced realm starts a sync session. You can pause and resume the sync session on the realm. Pausing a sync session only pauses that realm's sync session. If you have more than one open realm, pause does not affect the sync sessions for other realms.

To pause synchronization, use the syncSession.pause() method. To resume synchronization, use the syncSession.resume() method.

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();
};

For most applications, there is no need to manually pause and resume a sync session. However, there are a few circumstances under which you may want to pause or suspend a sync session:

  • You only want to sync after the user takes a specific action

  • You only want to sync during a certain time of the day

  • You don't want to attempt to sync when there is poor network connectivity

  • You want to explicitly force a sync session to connect

In the case of poor network connectivity, continually trying to establish a network connection can drain the user's device battery.

The case of explicitly forcing a sync session to connect is most commonly related to being offline for some time. The sync client attempts to connect, and upon failure, goes into exponential backoff. After being offline for a long time, the client may not immediately reconnect. Pausing and resuming the sync session explicitly forces the connection.

When you do pause a sync session, keep these things in mind:

  • If the client may be offline longer than the client maximum offline time, the client will be unable to resume syncing and must perform a client reset.

  • Pausing a sync session pauses it in both directions. Changes that your app makes on the device do not sync with the backend, and changes to the data in the backend or on other devices do not sync to the device. There is no way to pause only uploads or pause only downloads.

  • Do not pause a sync session if you want a client to permanently stop syncing with the backend. To permanently stop syncing, copy the contents of the synced realm into a non-synced realm, and use the non-synced realm in the client.

Do not pause sync to stop syncing for indefinite time periods or time ranges in months and years. The functionality is not designed or tested for these use cases. You could encounter a range of issues when using it this way.

To asynchronously wait for all changes to upload to Atlas from your synced realm, call uploadAllLocalChanges(). This method returns true when all changes have been uploaded.

realm.write(() => {
realm.create(Doggie, {
_id: new BSON.ObjectID(),
owner_id: app.currentUser!.id,
name: "Maui",
age: 3,
});
});
await realm.syncSession?.uploadAllLocalChanges();

To asynchronously wait for all changes on Atlas to download from the Device Sync server to your synced realm, call downloadAllServerChanges(). This method returns true when all changes have been downloaded.

await realm.syncSession?.downloadAllServerChanges();

You can specify a request timeout on the App configuration. With a timeout specified, you can set cancelWaitsOnNonFatalErrors on your BaseSyncConfiguration. When true and the timeout interval arrives, any any outstanding work that is awaiting uploads and downloads cancels. When this setting is false, awaiting uploads and downloads does not cancel because Realm treats these timeouts as non-fatal errors.

For more information, refer to Configure a Timeout for the App Client and Cancel Asynchronous Operations after a Timeout.

To check the upload and download progress for a sync session, add a progress notification using the syncSession.addProgressNotification() method.

The syncSession.addProgressNotification() method takes in the following three parameters:

  • A direction parameter. Set to "upload" to register notifications for uploading data. Set to "download" to register notifications for downloading data.

  • A mode parameter. Set to "reportIndefinitely" for the notifications to continue until the callback is unregistered using syncSession.removeProgressNotification(). Set to "forCurrentlyOutstandingWork" for the notifications to continue until only the currently transferable bytes are synced.

  • A callback function parameter that has the arguments transferred and transferable. transferred is the current number of bytes already transferred. transferable is the total number of bytes already transferred plus the number of bytes pending transfer.

Note

Flexible Sync progress notifications are not yet fully supported. When using Flexible Sync, downloads only report notifications after changes are integrated. Partition-Based Sync provides ongoing notifications as changes progress downloading. Uploads report ongoing progress notifications for both Sync Modes.

Example

In the following example, an application developer registers a callback on the syncSession to listen for upload events indefinitely. The developer writes to the realm and then unregisters the syncSession notification callback.

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,
});
});

To check the current state of the connection to the server, call the syncSession.connectionState() method.

Realm's offline-first design means that you generally don't need to check the current network connection state. That said, the syncSession.connectionState() method is available if your app needs to gets the current state of the connection to the server.

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;

Enable session multiplexing to consolidate multiple sync sessions of a Realm app. Only use session multiplexing if you see errors about reaching the file descriptor limit, and you know you are using many sync sessions.

To enable session multiplexing, call Realm.App.Sync.enableSessionMultiplexing() with your Realm.App.

Example

Realm.App.Sync.enableSessionMultiplexing(app);

Back

Manage Flexible Sync Subscriptions