Manage a Sync Session - Flutter SDK
On this page
Atlas Device Sync with Flexible Sync uses subscriptions and permissions to determine which data to sync between MongoDB Atlas and your app.
You can add, update, and remove query subscriptions to determine which data syncs to the client device.
Enabling Flexible Sync in Your Realm Application requires a non-sharded MongoDB Atlas cluster running MongoDB 5.0 or greater
Before You Begin
To use Flexible Sync in a Flutter application:
Manage Your Subscriptions
When configuring Flexible Sync on the backend, you specify which fields your client application can query. In the client application, use the Realm.subscriptions property to manage a set of subscriptions to specific queries on queryable fields.
You can:
- Get a list of all subscriptions
- Add subscriptions
- Check subscription state
- Update a subscription with a new query
- Remove subscriptions
When the data matches the subscription, and the authenticated user has the appropriate permissions, Atlas Device Sync syncs the backend data with the client app.
You can specify a string name for your subscription. If you do not give your
subscription a name, the name is set to null
.
When you create a subscription, Realm looks for data matching a query on a specific object type. In your Flexible Sync subscriptions, you can have subscriptions on several different object types or several queries on the same object type.
Get Subscriptions
When using Flexible Sync, you can access a
SubscriptionSet, a
collection of subscriptions, through the Realm.subscriptions
property.
You can use this subscriptions set to add queries to this list of subscriptions and update existing subscriptions, as shown in the examples below.
SubscriptionSet subscriptions = realm.subscriptions;
Add a Query to the Set of Subscriptions
You must perform all mutations on the subscriptions set within an update block. To create an update block, call SubscriptionSet.update().
The update block callback function, includes a MutableSubscriptionSet() object as an argument.
You can modify your method on the SubscriptionSet
to add a query to the subscription.
Flexible Sync does not support all the operators available in Realm Query Language. See Flexible Sync RQL Limitations for details.
The MutableSubscriptionSet.add()
method takes three arguments:
RealmResults query
: Required. ARealmResults
object that you can create using the Realm Query Language query.String name
: Optional. Name for the subscription that you can refer to.bool update
: Optional. When true, adding a subscription with an existing name replaces the existing query with the new query. Only use with named subscriptions.
If you add a duplicate unnamed subscription with the same query, Realm automatically removes it; adding an identical named subscription is a no-op. Therefore, in both cases, duplicate subscriptions are ignored.
You can add a single query, or batch multiple queries within a SubscriptionSet.update
block. Performing query updates is an expensive operation on the server. We
strongly advise designing your application to minimize subscription updates.
You can do this by creating all subscriptions in a single update block
the first time the user launches the app and batching any follow-up changes
to the subscription set.
In the example below, we subscribe to two queries.
final planeQuery = realm.all<Plane>(); final longTrainQuery = realm.query<Train>("numCars >= 5"); realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { mutableSubscriptions.add(planeQuery, name: "planes"); mutableSubscriptions.add(longTrainQuery, name: 'long-trains', update: true); }); await realm.subscriptions.waitForSynchronization();
Update Subscriptions with a New Query
You can update a named subscription with a new query. To update a subscription's
query, open an update block with SubscriptionSet.update()
.
In the callback function of the update block, pass the following arguments to MutableSubscriptionSet.add()
:
- The new query
- The name of the subscription that you want to update
update: true
You cannot update an unnamed subscription. Alternatively, you can delete the unnamed subscription, and create a new subscription with the desired query.
In the following example, long trains are re-defined to be any trains that have more than 10 cars.
final longerTrainQuery = realm.query<Train>("numCars > 10"); realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { mutableSubscriptions.add(longerTrainQuery, name: 'long-trains', update: true); });
Remove Subscriptions
To remove subscriptions from the subscription set, you can:
- Remove a single subscription with the given query
- Remove a single subscription with the given name
- Remove a single subscription with the subscription reference
- Remove all subscriptions
When you remove a subscription query, the server also removes synced data from the client device.
Remove a Subscription by Query
Within an update block, you can remove a specific subscription by query.
Open an update block with SubscriptionSet.update()
. Pass the Subscription
to
MutableSubscriptionSet.removeByQuery().
In the following example, the subscription for all Plane
objects is removed.
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { mutableSubscriptions.removeByQuery(realm.all<Plane>()); });
Remove a Subscription by Name
Within an update block, you can remove a specific subscription by name. Pass the name to MutableSubscriptionSet.removeByName()
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { mutableSubscriptions.removeByName('long-trains'); });
Remove a Subscription by Reference
You can remove a subscription if you have a reference to its Subscription object.
Within a subscription update block, pass the Subscription
reference to
MutableSubscriptionSet.remove().
Subscription sub = realm.subscriptions[0]; realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { mutableSubscriptions.remove(sub); });
Remove All Subscriptions
Within a subscription update block, you can remove all unnamed subscriptions from the subscriptions set with MutableSubscriptionSet.clear().
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { mutableSubscriptions.clear(); });
Wait for Subscription Changes to Sync
Mutating the subscription set within an update block is only one part of changing a subscription. After the local subscription change, the realm synchronizes with the server to resolve any updates to the data due to the subscription change. This includes adding or removing data from the synced realm.
Use Realm.subscriptions.waitForSynchronization() to wait for the server to acknowledge this set of subscriptions. If the server rejects the change, and an exception is thrown.
An exception may occur if:
- You subscribe to an unsupported query. Subscribing to an unsupported query will pause synchronization. To resume synchronization, remove the unsupported query.
- You are performing an invalid action, such as adding an object that does not match a subscription. This triggers a client reset: data is erased from the realm, and a new copy of the data is created without any subscriptions in the set.
await realm.subscriptions.waitForSynchronization();