From 0d156496fef003846ee7d2b3073691990a55ef18 Mon Sep 17 00:00:00 2001 From: cbullinger Date: Thu, 21 Dec 2023 12:31:06 -0500 Subject: [PATCH 1/4] Update Manage Sync Subscriptions page with new subscribe API --- .../test/manage_sync_subscription_test.dart | 99 ++++++++++-- ...nippet.add-subscription-subscribe-api.dart | 5 + ...t.remove-subscription-unsubscribe-api.dart | 2 + ...pet.update-subscription-subscribe-api.dart | 6 + ...snippet.wait-first-time-subscribe-api.dart | 6 + ...ippet.wait-with-timeout-subscribe-api.dart | 7 + .../sync/manage-sync-subscriptions.txt | 150 +++++++++++++++++- 7 files changed, 260 insertions(+), 15 deletions(-) create mode 100644 source/examples/generated/flutter/manage_sync_subscription_test.snippet.add-subscription-subscribe-api.dart create mode 100644 source/examples/generated/flutter/manage_sync_subscription_test.snippet.remove-subscription-unsubscribe-api.dart create mode 100644 source/examples/generated/flutter/manage_sync_subscription_test.snippet.update-subscription-subscribe-api.dart create mode 100644 source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-first-time-subscribe-api.dart create mode 100644 source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-with-timeout-subscribe-api.dart diff --git a/examples/dart/test/manage_sync_subscription_test.dart b/examples/dart/test/manage_sync_subscription_test.dart index 1e242dee50..b169343611 100644 --- a/examples/dart/test/manage_sync_subscription_test.dart +++ b/examples/dart/test/manage_sync_subscription_test.dart @@ -61,8 +61,8 @@ void main() { final planeQuery = realm.all(); final longTrainQuery = realm.all().query("numCars >= 4"); realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { - mutableSubscriptions.add(planeQuery, name: "all-planes"); - mutableSubscriptions.add(longTrainQuery, name: 'long-trains'); + mutableSubscriptions.add(planeQuery, name: "all-planes"); // +1 + mutableSubscriptions.add(longTrainQuery, name: 'long-trains'); // +1 }); await realm.subscriptions.waitForSynchronization(); }); @@ -75,6 +75,7 @@ void main() { await Future.delayed(Duration(milliseconds: 300)); Realm.deleteRealm(realm.config.path); }); + // Starting with 2 subscriptions from setUp: all-planes, long-trains test('Add query to subscription set', () async { // :snippet-start: add-subscription final planeQuery = realm.all(); @@ -86,13 +87,13 @@ void main() { }); await realm.subscriptions.waitForSynchronization(); // :snippet-end: - expect(realm.subscriptions.length, 3); + expect(realm.subscriptions.length, 3); // +1 planes }); test('Get subscriptions', () async { // :snippet-start: get-subscriptions final subscriptions = realm.subscriptions; // :snippet-end: - expect(subscriptions.length, 2); + expect(subscriptions.length, 2); // 0 }); test('Wait for subscription changes to sync', () async { // :snippet-start: wait-for-subscription-change @@ -110,8 +111,8 @@ void main() { name: 'long-trains', update: true); }); // :snippet-end: - expect(realm.subscriptions.findByName('long-trains')?.queryString.trim(), - "numCars > 10"); + expect(realm.subscriptions.length, 2); // 0 + expect(realm.subscriptions.findByName('long-trains')?.queryString.trim(), "numCars > 10"); }); test('Remove subscription by query', () async { // :snippet-start: remove-subscriptions-by-query @@ -119,7 +120,7 @@ void main() { mutableSubscriptions.removeByQuery(realm.all()); }); // :snippet-end: - // expect(realm.subscriptions.length, 1); + expect(realm.subscriptions.length, 1); // -1 }); test('Remove subscription by name', () async { // :snippet-start: remove-subscriptions-by-name @@ -127,7 +128,7 @@ void main() { mutableSubscriptions.removeByName('long-trains'); }); // :snippet-end: - expect(realm.subscriptions.length, 1); + expect(realm.subscriptions.length, 1); // -1 }); test('Remove all subscriptions by reference', () async { // :snippet-start: remove-subscriptions-by-reference @@ -136,7 +137,7 @@ void main() { mutableSubscriptions.remove(sub); }); // :snippet-end: - expect(realm.subscriptions.length, 1); + expect(realm.subscriptions.length, 1); // -1 }); test('Remove all subscriptions by object type', () async { // :snippet-start: remove-subscriptions-by-object-type @@ -144,7 +145,7 @@ void main() { mutableSubscriptions.removeByType(); }); // :snippet-end: - expect(realm.subscriptions.length, 1); + expect(realm.subscriptions.length, 1); // -1 }); test('Remove all subscriptions', () async { // :snippet-start: remove-all-subscriptions @@ -152,6 +153,84 @@ void main() { mutableSubscriptions.clear(); }); // :snippet-end: + expect(realm.subscriptions, isEmpty); // clear all + }); + test('Add query with subscribe api', () async { + // :snippet-start: add-subscription-subscribe-api + final boatQuery = realm.all(); + final bigPlaneQuery = realm.query("numSeats > 100"); + + final boatSubscription = await boatQuery.subscribe(name: "boats"); + final planeSubscription = await bigPlaneQuery.subscribe(name: "big-planes"); + // :snippet-end: + expect(realm.subscriptions.length, 4); // +2 + expect(realm.subscriptions.findByName("boats")?.queryString.trim(), "TRUEPREDICATE"); + expect(realm.subscriptions.findByName("big-planes")?.queryString.trim(), "numSeats > 100"); + }); + test('Update query with subscribe api', () async { + final planeQuery = realm.query("numSeats > 100"); + planeQuery.subscribe(name: "big-planes"); + // :snippet-start: update-subscription-subscribe-api + final updatedPlaneQuery = realm.query("numSeats > 200"); + + final planeSubscription = await updatedPlaneQuery.subscribe( + name: "big-planes", + update: true + ); + // :snippet-end: + expect(realm.subscriptions.length, 3); // +1 + final updatedSubscription = realm.subscriptions.findByName("big-planes"); + expect(updatedSubscription?.queryString.trim(), "numSeats > 200"); + }); + test('Wait for query to sync with subscribe api', () async { + realm.write(() { + realm.deleteAll(); + realm.addAll([ + Plane(1, "Plane1", 201), + Plane(2, "Plane2", 50) + ]); + }); + realm.syncSession.waitForUpload(TimeoutCancellationToken(Duration(seconds: 5))); + // :snippet-start: wait-first-time-subscribe-api + final bigPlaneQuery = realm.query("numSeats > 100"); + + final planeSubscription = await bigPlaneQuery.subscribe( + name: "firstTimeSync", + waitForSyncMode: WaitForSyncMode.firstTime, + ); + // :snippet-end: + expect(realm.subscriptions.length, 3); // +1 + expect(bigPlaneQuery.length, 1); + }); + test('Wait with timeout with subscribe api', () async { + realm.write(() { + realm.deleteAll(); + realm.addAll([ + Plane(1, "Plane1", 201), + Plane(2, "Plane2", 500) + ]); + }); + // :snippet-start: wait-with-timeout-subscribe-api + final bigPlaneQuery = realm.query("numSeats > 200"); + + final planeSubscription = await bigPlaneQuery.subscribe( + name: "alwaysWaitSync", + waitForSyncMode: WaitForSyncMode.always, + cancellationToken: TimeoutCancellationToken(Duration(seconds: 5)), + ); + // :snippet-end: + expect(realm.subscriptions.length, 3); // +1 + expect(bigPlaneQuery.length, 2); + + }); + test('Remove subscription with unsubscribe api', () async { + final planeQuery = realm.all(); + final trainSubscription = realm.subscriptions.findByName("long-trains")?.queryString; + final trainQuery = realm.query(trainSubscription!); + // :snippet-start: remove-subscription-unsubscribe-api + planeQuery.unsubscribe(); + trainQuery.unsubscribe(); + // :snippet-end: expect(realm.subscriptions, isEmpty); }); }); diff --git a/source/examples/generated/flutter/manage_sync_subscription_test.snippet.add-subscription-subscribe-api.dart b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.add-subscription-subscribe-api.dart new file mode 100644 index 0000000000..516bfb8fae --- /dev/null +++ b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.add-subscription-subscribe-api.dart @@ -0,0 +1,5 @@ +final boatQuery = realm.all(); +final bigPlaneQuery = realm.query("numSeats > 100"); + +final boatSubscription = await boatQuery.subscribe(name: "boats"); +final planeSubscription = await bigPlaneQuery.subscribe(name: "big-planes"); diff --git a/source/examples/generated/flutter/manage_sync_subscription_test.snippet.remove-subscription-unsubscribe-api.dart b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.remove-subscription-unsubscribe-api.dart new file mode 100644 index 0000000000..15d922174e --- /dev/null +++ b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.remove-subscription-unsubscribe-api.dart @@ -0,0 +1,2 @@ +planeQuery.unsubscribe(); +trainQuery.unsubscribe(); diff --git a/source/examples/generated/flutter/manage_sync_subscription_test.snippet.update-subscription-subscribe-api.dart b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.update-subscription-subscribe-api.dart new file mode 100644 index 0000000000..0c04bb3bbe --- /dev/null +++ b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.update-subscription-subscribe-api.dart @@ -0,0 +1,6 @@ +final updatedPlaneQuery = realm.query("numSeats > 200"); + +final planeSubscription = await updatedPlaneQuery.subscribe( + name: "big-planes", + update: true +); diff --git a/source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-first-time-subscribe-api.dart b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-first-time-subscribe-api.dart new file mode 100644 index 0000000000..f70a16a5ec --- /dev/null +++ b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-first-time-subscribe-api.dart @@ -0,0 +1,6 @@ +final bigPlaneQuery = realm.query("numSeats > 100"); + +final planeSubscription = await bigPlaneQuery.subscribe( + name: "firstTimeSync", + waitForSyncMode: WaitForSyncMode.firstTime, +); diff --git a/source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-with-timeout-subscribe-api.dart b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-with-timeout-subscribe-api.dart new file mode 100644 index 0000000000..a4a729df95 --- /dev/null +++ b/source/examples/generated/flutter/manage_sync_subscription_test.snippet.wait-with-timeout-subscribe-api.dart @@ -0,0 +1,7 @@ +final bigPlaneQuery = realm.query("numSeats > 200"); + +final planeSubscription = await bigPlaneQuery.subscribe( + name: "alwaysWaitSync", + waitForSyncMode: WaitForSyncMode.always, + cancellationToken: TimeoutCancellationToken(Duration(seconds: 5)), +); diff --git a/source/sdk/flutter/sync/manage-sync-subscriptions.txt b/source/sdk/flutter/sync/manage-sync-subscriptions.txt index d530b2ff07..aecb8645db 100644 --- a/source/sdk/flutter/sync/manage-sync-subscriptions.txt +++ b/source/sdk/flutter/sync/manage-sync-subscriptions.txt @@ -5,6 +5,14 @@ Manage Sync Subscriptions - Flutter SDK ======================================= +.. meta:: + :keywords: code example + :description: Create, update, and delete query subscriptions used by Atlas Device Sync. + +.. facet:: + :name: genre + :values: reference + .. contents:: On this page :local: :backlinks: none @@ -17,10 +25,10 @@ to determine which data to sync between Atlas and your app. You can add, update, and remove query subscriptions to determine which data syncs to the client device. -.. include:: /includes/note-flexible-sync-prerequisite.rst +Prerequisites +------------- -Before You Begin ----------------- +.. include:: /includes/note-flexible-sync-prerequisite.rst To use Flexible Sync in a Flutter application: @@ -53,8 +61,120 @@ You subscription queries can either: refer to the :ref:`Flexible Sync RQL Limitations ` section. -Manage Your Subscriptions -------------------------- +.. _flutter-subscribe-api: + +Subscribe to Queries +-------------------- + +.. versionadded:: v1.6.0 + +Flutter v1.6.0 adds experimental APIs that subscribe to and unsubscribe +from a query's results. These APIs abstract away the details of +manually adding and removing subscriptions. + +For all subscriptions, you need :an :ref:`authenticated user ` and a :ref:`synced realm `. + +If you need more control over subscriptions for performance optimization or +business logic reasons, you can +:ref:`manually manage the subscription set ` +using the ``subscriptions`` API. Refer to the +:ref:`Performance Considerations ` +section on this page for more information. + +Subscribe to a Query +~~~~~~~~~~~~~~~~~~~~ + +You can subscribe to the ``RealmResults`` of a query using the +:flutter-sdk:`subscribe() ` +method. When called, the The SDK creates the new subscription and adds it to the +``MutableSubscriptionSet``, similar to +:ref:`manually creating subscription `. + +You can optionally pass a unique subscription name for the query. If you +add a subscription with the same name as an existing subscription, the SDK +overwrites the existing subscription. + +If you do not pass a subscription name, the name is set to ``null``, and +the subscription identifier is based on the query string. This means that +every time your query string changes, ``subscribe()`` creates a new subscription. + +To subscribe to a query, pass the following arguments to ``subscribe()``: + +- ``RealmResults query``: Required. A ``RealmResults`` object that you can create using the + :ref:`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. When false, the SDK + throws an exception for duplicate subscriptions. Only use with named subscriptions. + +In the following example, we subscribe to 2 new named queries. + +.. literalinclude:: /examples/generated/flutter/manage_sync_subscription_test.snippet.add-subscription-subscribe-api.dart + :language: dart + +.. tip:: Specify a Subscription Name + + We recommend that you always specify a subscription name, especially if your application uses + multiple subscriptions. This makes finding and managing + your subscriptions easier. + +Wait for a Query Subscription to Sync +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you subscribe to a query's results, the results do not contain objects +until synced data is downloaded. When you do need to wait for synced objects to +finish downloading, configure the :flutter-sdk:`waitForSyncMode ` option. You can specify +different behavior for your subscriptions and how they handle writing for +downloads. + +This example uses the ``firstTime`` option, which is the default behavior. +A subscription with ``firstTime`` behavior only waits for sync to finish when a +subscription is first created. + +.. literalinclude:: /examples/generated/flutter/manage_sync_subscription_test.snippet.wait-first-time-subscribe-api.dart + :language: dart + :emphasize-lines: 5 + +The other supported ``waitForSyncMode`` options are: + +- ``always``: Wait to download matching objects every time your app launches. + The app must have an internet connection at every launch. +- ``never``: Never wait to download matching objects. The app needs an internet + connection for the user to authenticate the first time the app launches, but + can open offline on + subsequent launches using cached credentials. + +You can optionally specify a :flutter-sdk:`cancellationToken ` +to limit how long the sync download runs: + +.. literalinclude:: /examples/generated/flutter/manage_sync_subscription_test.snippet.wait-with-timeout-subscribe-api.dart + :language: dart + :emphasize-lines: 5-6 + +Unsubscribe from a Query +~~~~~~~~~~~~~~~~~~~~~~~~ + +Subscriptions persist across user sessions unless you unsubscribe from them. +You can unsubscribe from a query's results using :flutter-sdk:`unsubscribe() `. + +This removes the subscription from the list of active subscriptions, similar to +:ref:`manually removing a subscription `. +Note that the results list may still contain objects after calling ``unsubscribe()`` +if another subscription exists that contains overlapping objects. + +When you call ``unsubscribe()`` on a query, the SDK removes any +subscriptions with queries that exactly match the one you call +``unsubscribe()`` on. This method returns before objects matching the +removed subscription are deleted from the realm. Sync continues in the +background based on the new set of subscriptions. + +.. literalinclude:: /examples/generated/flutter/manage_sync_subscription_test.snippet.remove-subscription-unsubscribe-api.dart + :language: dart + +.. _flutter-manually-manage-subscriptions: + +Manually Manage Subscriptions +----------------------------- When configuring Flexible Sync on the backend, you specify which fields your client application can query. In the client application, use the @@ -285,3 +405,23 @@ Flexible Sync RQL Requirements and Limitations ----------------------------------------------- .. include:: /includes/flex-sync-limitations.rst + +.. _flutter-flex-sync-performance-considerations: + +Performance Considerations +-------------------------- + +API Efficiency +~~~~~~~~~~~~~~ + +Managing multiple subscriptions with the ``.subscribe()`` +API described in the :ref:`flutter-subscribe-api` section +is less efficient than performing batch updates when you +manually manage subscriptions through the subscription set API. For better performance when +making multiple subscription changes, use the ``subscriptions.update`` API described in the +:ref:`flutter-manually-manage-subscriptions` section. + +Group Updates for Improved Performance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. include:: /includes/sync-memory-performance.rst \ No newline at end of file From 925ad06cc6ff4e2124409bce297f6191fe09120e Mon Sep 17 00:00:00 2001 From: cbullinger Date: Tue, 26 Dec 2023 14:29:55 -0500 Subject: [PATCH 2/4] Add lines for test readability --- .../test/manage_sync_subscription_test.dart | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/examples/dart/test/manage_sync_subscription_test.dart b/examples/dart/test/manage_sync_subscription_test.dart index b169343611..79fa047e14 100644 --- a/examples/dart/test/manage_sync_subscription_test.dart +++ b/examples/dart/test/manage_sync_subscription_test.dart @@ -47,15 +47,18 @@ void main() { Credentials.emailPassword("lisa@example.com", "abc123"); currentUser = await app.logIn(credentials); }); + tearDownAll(() async { await app.currentUser?.logOut(); }); + setUp(() async { final config = Configuration.flexibleSync( currentUser, [Plane.schema, Train.schema, Boat.schema], path: 'flex-${generateRandomString(10)}.realm', ); + realm = Realm(config); await realm.subscriptions.waitForSynchronization(); final planeQuery = realm.all(); @@ -66,6 +69,7 @@ void main() { }); await realm.subscriptions.waitForSynchronization(); }); + tearDown(() async { realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { mutableSubscriptions.clear(); @@ -75,6 +79,7 @@ void main() { await Future.delayed(Duration(milliseconds: 300)); Realm.deleteRealm(realm.config.path); }); + // Starting with 2 subscriptions from setUp: all-planes, long-trains test('Add query to subscription set', () async { // :snippet-start: add-subscription @@ -87,14 +92,16 @@ void main() { }); await realm.subscriptions.waitForSynchronization(); // :snippet-end: - expect(realm.subscriptions.length, 3); // +1 planes + expect(realm.subscriptions.length, 3); // +1 subscription }); + test('Get subscriptions', () async { // :snippet-start: get-subscriptions final subscriptions = realm.subscriptions; // :snippet-end: - expect(subscriptions.length, 2); // 0 + expect(subscriptions.length, 2); // +0 }); + test('Wait for subscription changes to sync', () async { // :snippet-start: wait-for-subscription-change await realm.subscriptions.waitForSynchronization(); @@ -111,9 +118,10 @@ void main() { name: 'long-trains', update: true); }); // :snippet-end: - expect(realm.subscriptions.length, 2); // 0 + expect(realm.subscriptions.length, 2); // +0 expect(realm.subscriptions.findByName('long-trains')?.queryString.trim(), "numCars > 10"); }); + test('Remove subscription by query', () async { // :snippet-start: remove-subscriptions-by-query realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { @@ -122,6 +130,7 @@ void main() { // :snippet-end: expect(realm.subscriptions.length, 1); // -1 }); + test('Remove subscription by name', () async { // :snippet-start: remove-subscriptions-by-name realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { @@ -130,6 +139,7 @@ void main() { // :snippet-end: expect(realm.subscriptions.length, 1); // -1 }); + test('Remove all subscriptions by reference', () async { // :snippet-start: remove-subscriptions-by-reference final sub = realm.subscriptions[0]; @@ -139,6 +149,7 @@ void main() { // :snippet-end: expect(realm.subscriptions.length, 1); // -1 }); + test('Remove all subscriptions by object type', () async { // :snippet-start: remove-subscriptions-by-object-type realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { @@ -147,6 +158,7 @@ void main() { // :snippet-end: expect(realm.subscriptions.length, 1); // -1 }); + test('Remove all subscriptions', () async { // :snippet-start: remove-all-subscriptions realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) { @@ -155,6 +167,7 @@ void main() { // :snippet-end: expect(realm.subscriptions, isEmpty); // clear all }); + test('Add query with subscribe api', () async { // :snippet-start: add-subscription-subscribe-api final boatQuery = realm.all(); @@ -167,6 +180,7 @@ void main() { expect(realm.subscriptions.findByName("boats")?.queryString.trim(), "TRUEPREDICATE"); expect(realm.subscriptions.findByName("big-planes")?.queryString.trim(), "numSeats > 100"); }); + test('Update query with subscribe api', () async { final planeQuery = realm.query("numSeats > 100"); planeQuery.subscribe(name: "big-planes"); @@ -182,6 +196,7 @@ void main() { final updatedSubscription = realm.subscriptions.findByName("big-planes"); expect(updatedSubscription?.queryString.trim(), "numSeats > 200"); }); + test('Wait for query to sync with subscribe api', () async { realm.write(() { realm.deleteAll(); @@ -202,6 +217,7 @@ void main() { expect(realm.subscriptions.length, 3); // +1 expect(bigPlaneQuery.length, 1); }); + test('Wait with timeout with subscribe api', () async { realm.write(() { realm.deleteAll(); @@ -223,6 +239,7 @@ void main() { expect(bigPlaneQuery.length, 2); }); + test('Remove subscription with unsubscribe api', () async { final planeQuery = realm.all(); final trainSubscription = realm.subscriptions.findByName("long-trains")?.queryString; From 05a431be71ab32b53b8682e7778dfccee0abbba9 Mon Sep 17 00:00:00 2001 From: cbullinger Date: Tue, 26 Dec 2023 14:32:29 -0500 Subject: [PATCH 3/4] Apply feedback --- source/sdk/flutter/sync/manage-sync-subscriptions.txt | 4 +--- source/sdk/react-native/sync-data/flexible-sync.txt | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/source/sdk/flutter/sync/manage-sync-subscriptions.txt b/source/sdk/flutter/sync/manage-sync-subscriptions.txt index aecb8645db..f8b6926dfa 100644 --- a/source/sdk/flutter/sync/manage-sync-subscriptions.txt +++ b/source/sdk/flutter/sync/manage-sync-subscriptions.txt @@ -123,9 +123,7 @@ Wait for a Query Subscription to Sync When you subscribe to a query's results, the results do not contain objects until synced data is downloaded. When you do need to wait for synced objects to -finish downloading, configure the :flutter-sdk:`waitForSyncMode ` option. You can specify -different behavior for your subscriptions and how they handle writing for -downloads. +finish downloading, configure the :flutter-sdk:`waitForSyncMode ` option. This example uses the ``firstTime`` option, which is the default behavior. A subscription with ``firstTime`` behavior only waits for sync to finish when a diff --git a/source/sdk/react-native/sync-data/flexible-sync.txt b/source/sdk/react-native/sync-data/flexible-sync.txt index 023661f4cf..643314e9bc 100644 --- a/source/sdk/react-native/sync-data/flexible-sync.txt +++ b/source/sdk/react-native/sync-data/flexible-sync.txt @@ -126,9 +126,7 @@ Wait for a Query Subscription to Sync When you subscribe to a query's results, the results do not contain objects until synced data is downloaded. When you do need to wait for synced objects to -finish downloading, configure the ``waitForSync`` option. You can specify -different behavior for your subscriptions and how they handle writing for -downloads. +finish downloading, configure the ``waitForSync`` option. This example uses the ``FirstTime`` option, which is the default behavior. A subscription with ``FirstTime`` behavior only waits for sync to finish when a From e01540ba10ca1dd78253f21f6800afea424df8de Mon Sep 17 00:00:00 2001 From: cbullinger <115956901+cbullinger@users.noreply.github.com> Date: Tue, 26 Dec 2023 14:33:09 -0500 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Kyle Rollins <115574589+krollins-mdb@users.noreply.github.com> --- source/sdk/flutter/sync/manage-sync-subscriptions.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/sdk/flutter/sync/manage-sync-subscriptions.txt b/source/sdk/flutter/sync/manage-sync-subscriptions.txt index f8b6926dfa..1d208d95e7 100644 --- a/source/sdk/flutter/sync/manage-sync-subscriptions.txt +++ b/source/sdk/flutter/sync/manage-sync-subscriptions.txt @@ -72,7 +72,7 @@ Flutter v1.6.0 adds experimental APIs that subscribe to and unsubscribe from a query's results. These APIs abstract away the details of manually adding and removing subscriptions. -For all subscriptions, you need :an :ref:`authenticated user ` and a :ref:`synced realm `. +For all subscriptions, you need an :ref:`authenticated user ` and a :ref:`synced realm `. If you need more control over subscriptions for performance optimization or business logic reasons, you can @@ -86,7 +86,7 @@ Subscribe to a Query You can subscribe to the ``RealmResults`` of a query using the :flutter-sdk:`subscribe() ` -method. When called, the The SDK creates the new subscription and adds it to the +method. When called, the SDK creates the new subscription and adds it to the ``MutableSubscriptionSet``, similar to :ref:`manually creating subscription `. @@ -101,13 +101,13 @@ every time your query string changes, ``subscribe()`` creates a new subscription To subscribe to a query, pass the following arguments to ``subscribe()``: - ``RealmResults query``: Required. A ``RealmResults`` object that you can create using the - :ref:`Realm Query Language query `. + :ref:`Realm Query Language `. - ``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. When false, the SDK throws an exception for duplicate subscriptions. Only use with named subscriptions. -In the following example, we subscribe to 2 new named queries. +In the following example, we subscribe to two new named queries. .. literalinclude:: /examples/generated/flutter/manage_sync_subscription_test.snippet.add-subscription-subscribe-api.dart :language: dart