Docs Menu

Docs HomeAtlas Device SDK

Manage Sync Subscriptions - C++ SDK

On this page

  • Prerequisites
  • Align Subscriptions with Backend App
  • Manage Your Subscriptions
  • Verify Number of Subscriptions or Find a Specific Subscription
  • Add Sync Subscriptions
  • Subscribe to All Objects of a Type
  • Subscribe to Objects that Match a Query
  • Update Sync Subscriptions
  • Remove Sync Subscriptions
  • Remove a Specific Subscription
  • Remove All Subscriptions
  • Refresh the Realm After Updating Subscriptions

Flexible Sync uses subscriptions and permissions to determine which data to sync between your Atlas App Services App and your client device. In the client, query subscriptions manage and filter the object types that can sync to the realm.

To use Flexible Sync in your app, you must:

The setup code for the examples on this page handles these prerequisites:

// Initialize the App, authenticate a user, and open the database
auto appConfig = realm::App::configuration();
appConfig.app_id = APP_ID;
auto app = realm::App(appConfig);
auto user = app.login(realm::App::credentials::anonymous()).get();
auto syncConfig = user.flexible_sync_configuration();
auto syncedRealm = realm::db(syncConfig);

Additionally, models used with Sync must contain a primary key property named _id. For more information on defining a model with a primary key, refer to Specify a Primary Key.

Your client-side subscription queries must align with the Device Sync configuration in your backend App Services App.

You subscription queries can either:

  • Query all objects of a type.

  • Query object of a type that match backend App's queryable fields.

To learn more about configuring queryable fields, refer to Queryable Fields in the App Services documentation.

A synced realm must have one or more subscriptions in order to be able to read and write data to the realm. You can only write data to the realm that matches one or more subscriptions, and matches the user's permissions. If you attempt to write objects to a realm that do not match a subscription, or for which the user does not have permission to perform the write, you get a compensating write from the server and the write reverts.

When configuring Flexible Sync on the backend, you specify which fields your client application can query. In the client application, the sync_subscription_set is a list of zero or more sync_subscription objects that determine what objects the realm can store.

The Realm C++ SDK also has a mutable_sync_subscription_set that enables you to add, change, and remove sync_subscription objects.

When your app first opens a synced realm, you may want to verify that it has the expected number of subscriptions or has a specific subscription.

You can get this information by accessing the subscriptions() public member function of a realm. This provides the sync_subscription_set where you can use the size() or find() member functions.

// Check the subscription count
CHECK(syncedRealm.subscriptions().size() == 1);
// Find a specific subscription by name
auto puppySubscription = *syncedRealm.subscriptions().find("puppies");
CHECK(puppySubscription.name == "puppies");
// Get information about the subscription
CHECK(puppySubscription.object_class_name == "Dog");
CHECK(puppySubscription.query_string == "age < 3");

To update a subscription set, use the subscription().updates() function. This gives you access to a mutable_sync_subscription_set where you can use the use the add() function to add a new Sync subscription.

This template requires the object type of the object you want to sync, and a string name for the subscription.

You can subscribe to all objects of a type. This enables the synced realm to read and write any objects of the type where the user's permissions match the server-side permissions.

auto updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.add<realm::Dog>("dogs");
})
.get();
// The .update() function returns a bool, which confirms whether or not the
// update succeeded
REQUIRE(updateSubscriptionSuccess == true);
// You can check the .size() of the subscription set, which tells you the
// number of sync_subscription objects in the set
CHECK(syncedRealm.subscriptions().size() == 1);

If you only want to subscribe to a subset of objects, provide a query to filter the subscription.

updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.add<realm::Dog>(
"puppies", [](auto &obj) { return obj.age < 3; });
})
.get();
REQUIRE(updateSubscriptionSuccess == true);
CHECK(syncedRealm.subscriptions().size() == 1);

When you filter a subscription, you cannot write objects that do not match the filter. In this example, the query matches Dog objects whose age is less than 3. The realm does not sync any dogs who are 3 or older. This filter also applies to writes. If you try to write a Dog object where the age is 4, you get a compensating write error and the write reverts.

Note

The C++ SDK does not yet support the full range of query expressions that the other SDKs provide.

To update a subscription set, use the subscription().updates() function. This gives you access to a mutable_sync_subscription_set where you can use the update_subscription() function to update a specific sync_subscription.

You can change a sync_subscription's query in an update. You can add, remove, or update the query string for a given sync_subscription.

updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.update_subscription<realm::Dog>(
"puppies", [](auto &obj) { return obj.age < 2; });
})
.get();
REQUIRE(updateSubscriptionSuccess == true);

To update a subscription set, use the subscription().updates() function. This gives you access to a mutable_sync_subscription_set where you can use the remove() or clear() functions to remove subscriptions.

You can remove a specific subscription by name using the remove() function. Removing a subscription by name throws an error if the subscription does not exist, so you should check for a subscription before removing it.

auto removeSubscriptionSuccess =
syncedRealm.subscriptions()
.update([](realm::mutable_sync_subscription_set &subs) {
subs.remove("dogs");
})
.get();
REQUIRE(removeSubscriptionSuccess == true);

You can remove all subscriptions in a subscription set using the clear() function.

// You can use .clear() inside a mutable_sync_subscription_set to clear all
// sync_subscription objects from the set
auto updateSubscriptionSuccess =
syncedRealm.subscriptions()
.update(
[](realm::mutable_sync_subscription_set &subs) { subs.clear(); })
.get();
CHECK(updateSubscriptionSuccess == true);
CHECK(syncedRealm.subscriptions().size() == 0);

After you update subscriptions, call refresh() on the realm. This updates the realm and outstanding objects managed by the realm to point to the most recent data.

syncedRealm.refresh();
←  Sync Data Between Devices - C++ SDKWrite Data to a Synced Realm - C++ SDK →