Docs Menu

Sync Changes Between Devices - Node.js SDK

On this page

Before you can access a synced realm from the client, you must:

  1. Enable sync in the Realm UI.
  2. Initialize the app
  3. Authenticate a user in your client project.
  4. Open a Flexible Synced Realm or Open a Partition-Based Synced Realm
Note
Sync method in the examples on this page

The examples on this page use Partition-Based Sync with the firehose partition strategy. This means that data is synced to the clients of all users with the same static partition value.

In the examples on this page, the static partition value is MyPartitionValue. All realms with the partition MyPartitionValue have access to any document with a matching partition value. The realm's Configuration object includes a SyncConfiguration with partitionValue: "MyPartitionValue".

Configuration
const config = {
schema: [DogSchema], // predefined schema
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
...rest of SyncConfiguration
},
};

For more information on how to configure Partition-Based Sync, refer to the Partition Strategies documentation.

You may want to sync changes in the background to display partial data to the user while the synced realm downloads data from the server, preventing the user experience from being blocked. We recommend syncing changes in the background for applications in which the user's device may go offline. To sync changes in the background, open a synced realm synchronously.

Create a OpenRealmBehaviorConfiguration object and set its type to "openImmediately".

const OpenRealmBehaviorConfiguration = {
type: "openImmediately",
};

Create a Configuration object, which must include the sync property defining a SyncConfiguration object. Set this OpenRealmBehaviorConfiguration object as the value for the newRealmFileBehavior and existingRealmFileBehavior fields of the SyncConfiguration.

const config = {
schema: [DogSchema], // predefined schema
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
// The behavior to use when this is the first time opening a realm.
newRealmFileBehavior: OpenRealmBehaviorConfiguration,
// The behavior to use when a realm file already exists locally,
// i.e. you have previously opened the realm.
existingRealmFileBehavior: OpenRealmBehaviorConfiguration,
},
};

Finally, call Realm.open() to open a synced realm. This will create a sync session and begin downloading any existing data from the server in the background.

const realm = await Realm.open(config);

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 OpenRealmBehaviorConfiguration = {
type: "openImmediately",
};
var config = {
schema: [DogSchema], // predefined schema
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
newRealmFileBehavior: OpenRealmBehaviorConfiguration,
existingRealmFileBehavior: OpenRealmBehaviorConfiguration,
},
};
let realm = await Realm.open(config);
const syncSession = realm.syncSession;
// Pause synchronization
syncSession.pause();
// Later, resume synchronization
syncSession.resume();
Note

Use the .pause() method to control when a device syncs. You should only use it for temporary and short-term pauses of syncing.

Examples of when to use .pause() include:

  • Syncing data only at specified time of day
  • Conserving device battery use

Don't use the .pause() method 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, and you could encounter a range of issues when using it this way.

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.
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 OpenRealmBehaviorConfiguration = {
type: "openImmediately",
};
var config = {
schema: [DogSchema], // predefined schema
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
newRealmFileBehavior: OpenRealmBehaviorConfiguration,
existingRealmFileBehavior: OpenRealmBehaviorConfiguration,
},
};
let realm = await Realm.open(config);
const syncSession = realm.syncSession;
syncSession.addProgressNotification(
"upload",
"reportIndefinitely",
(transferred, transferable) => {
console.log(`${transferred} bytes has been transferred`);
console.log(
`There are ${transferable} total transferable bytes, including the ones that have already been transferred`
);
}
);
// Upload something
let dog;
realm.write(() => {
dog = realm.create("Dog", {
name: "Fido",
age: 2,
});
});
// use dog
// remember to unregister the progress notifications
syncSession.removeProgressNotification((transferred, transferable) => {
console.log(`There was ${transferable} total transferable bytes`);
console.log(`${transferred} bytes were transferred`);
});

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

Tip

MongoDB 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.

var config = {
schema: [DogSchema], // predefined schema
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
},
};
let realm = await Realm.open(config);
const syncSession = realm.syncSession;
const connectionState = syncSession.connectionState();

You can set the realm Sync client log level by calling Realm.App.Sync.setLogLevel() with your Realm.App.

Example

In the following example, an application developer sets the sync client log level to "debug".

Realm.App.Sync.setLogLevel(app, "debug");
Tip

To diagnose and troubleshoot errors while developing your application, set the log level to debug or trace. For production deployments, decrease the log level for improved performance.

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

While developing an application that uses Realm Sync, you should set an error handler. This error handler will detect and respond to any failed sync-related API calls.

Set an error handler by registering an error callback as part of the SyncConfiguration.

var config = {
schema: [DogSchema], // predefined schema
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
error: (_session, error) => {
(error) => {
console.log(error.name, error.message);
};
},
},
};
const realm = await Realm.open(config);

You can customize behavior in the event of a client reset error with a custom error handler function:

let realm = await Realm.open(config);
function errorSync(_session, error) {
if (realm) {
if (error.name === "ClientReset") {
const realmPath = "<Your Realm Path>";
realm.close();
console.log(`Error ${error.message}, need to reset ${realmPath}…`);
Realm.App.Sync.initiateClientReset(app, realmPath); // pass your realm app instance, and realm path to initiateClientReset()
console.log(`Creating backup from ${error.config.path}…`);
// Move backup file to a known location for a restore
fs.renameSync(error.config.path, realmPath + "~");
// Discard the reference to the realm instance
realm = null;
} else {
console.log(`Received error ${error.message}`);
}
}
}
var config = {
schema: [DogSchema], // predefined schema
sync: {
user: app.currentUser,
partitionValue: "MyPartitionValue",
error: errorSync,
},
};
Tip

To see how to recover unsynced local changes in a client reset, check out this example on GitHub.

←  Authenticate Users - Node.js SDKFlexible Sync - Node.js SDK →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.