Realm Stream changes

Hello,

I have a small question regarding Realm Stream( realmServices.realm.query<Item>("TRUEPREDICATE SORT(_id ASC)").changes). Considering this line of code: link, does it mean that if the collection is empty, the loader would keep spinning indefinitely? Is there a way to determine when the query has finished and the collection is empty, so that this can be displayed in the UI?

No, date == null means nothing has been pumped on the stream yet. The stream will pump the first value almost immediately. If the db is empty, then data.results will be empty, and an empty ListView will rendered in the code you link to.

@nielsenko, thanks for a reply.
My issue is in …'almost immediately '. For the first sync between client and cloud if collection is big it would not immediately pull the data but Stream emits empty value at first emission and Im not able to implement loading screen. I’ve tried to .transform a stream to wait for the data but then I get an issue where for empty collections I end up with infinite loading :frowning:

@Riverpod(keepAlive: true)
class SalePointsStreamSlice extends _$SalePointsStreamSlice {
  late Realm realm;

  @override
  Stream<RealmResultsChanges> build() async* {
    realm = ref.read(realmDbServiceProvider);

    final allSalePoints = realm.all<SalePoint>().changes;

    final transformedStream = allSalePoints.transform(
      StreamTransformer<RealmResultsChanges<SalePoint>,
          RealmResultsChanges>.fromHandlers(
        handleData: (RealmResultsChanges<SalePoint>? data, sink) {
          /// causing infinite loading for empty collections.
          if (data != null) {
            sink.add(data);
          }
          /// workaround that is not ideal
          /// Future.delayed(const Duration(seconds: 10), () {
          ///     sink.add(data);
          /// });
          /// if (data.results.isNotEmpty) {
          ///    sink.add(data);
         /// }
        },
      ),
    );
    yield* transformedStream;
  }

I might be wrong in my assumptions, but if not is there any work around I could use?

P.S. By the way, thanks for ‘Observable Flutter’ session. Nice one.

If I understand correctly, you should use:

  final token = TimeoutCancellationToken(const Duration(seconds: 3)); // or how long you are prepared to wait
  await realm.syncSession.waitForDownload(token);

This ensures that all inbound data is downloaded, as per current subscriptions. Be aware that this call will block, if you cannot access Atlas for some reason, hence it is important to pass a cancellation token to allow the operation to be aborted. Here I use a TimeoutCancellationToken with a 3s duration, but you can also hook it up to a cancel button in the UI or whatever.

For the widget tree, you can use a future builder (for waitForDownload) that wraps a stream builder (for changes). Or use riverpod to orchestrate.

And thanks! I’m glad you could enjoyed the MongoDB & Realm episode on Observable Flutter

Last questions :smiling_face:.
waitForDownload(...) - ‘Waits for the Session to finish all pending downloads.’ Doest it mean that it waits for download for ALL ADDED SUBSCRIPTIONS, so If I’ve added 5 sub from 5 collections it will wait for all data to sync? Same question about getProgressStream(...).
Asking this because I’ve noticed that when Im adding/removing subscriptions and initializing fresh synced realm amount of bytes stays the same.

One last answer then :slight_smile:

Yes to both, but last I checked there was an issue with realm-core (or really the Atlas Device Sync service), that makes the events pumped on getProgressStream inaccurate and mostly pointless.

For full disclosure, I no longer work for MongoDB. Just hanging around of old habit.

Thanks a lot @nielsenko. I wish you all the best in a ‘new journey’. GOOD LUCK.

@Desislava_St_Stefanova any help would be appreciated.
Is there any way to resolve my issue with first SYNC. (When sync starts it emits empty value that cause issues with loading, no data state).
I’ve tried to use the solution Kasper suggested but TimeoutCancellationToken class doesn’t exist.

Thank you @shyshkov.o.a. BTW, you need to import the cancellation_token package to get TimeoutCancellationToken.

Like @Kasper_Nielsen1 for me, the @Desislava_St_Stefanova account belonged to desistefanova when she was still with MongoDB. She will no longer be notified by using that tag.

However, perhaps she still responds to her community account @Desislava_Stefanova?

Tested await realm.syncSession.waitForDownload() and it seems to work not as expected. It resolves before the actual download finishes. @Mongo_BD could you help?
LOGS:

flutter: 2023-10-26T12:36:25.825513: [INFO] Realm: Realm sync client ([realm-core-13.17.2])
flutter: 2023-10-26T12:36:25.826543: [INFO] Realm: Platform: iOS Darwin 23.0.0 Darwin Kernel Version 23.0.0: Fri Sep 15 14:43:05 PDT 2023; root:xnu-10002.1.13~1/RELEASE_ARM64_T6020 arm64
flutter: 2023-10-26T12:36:25.829123: [INFO] Realm: Connection[1]: Session[1]: Binding '/Users/olegshyshkov/Library/Developer/CoreSimulator/Devices/27F2D33B-7F82-4BE0-A0C4-6376B29B1C8C/data/Containers/Data/Application/E3E88586-969A-4526-AF2A-A23B564654E7/Documents/mongodb-realm/devicesync-uedcn/64c3ecfc915240965aef5c7d/default.realm' to ''
flutter: 2023-10-26T12:36:25.829214: [INFO] Realm: Connection[1]: Session[1]: client_reset_config = false, Realm exists = true, client reset = false
flutter: 2023-10-26T12:36:25.829287: [INFO] Realm: Connection[1]: Connecting to 'wss://ws.eu-central-1.aws.realm.mongodb.com:443/api/client/v2.0/app/devicesync-uedcn/realm-sync'
flutter: 2023-10-26T12:36:25.869792: [INFO] Realm: Connected to endpoint '3.124.220.115:443' (from '192.168.1.138:58446')
flutter: 2023-10-26T12:36:26.360776: [INFO] Realm: Connection[1]: Connected to app services with request id: "653a412ab77a706c9936b7d1"
flutter: 2023-10-26T12:36:27.955290: [INFO] Realm: Connection[1]: Session[1]: Begin processing pending FLX bootstrap for query version 0. (changesets: 1, original total changeset size: 2348)
flutter: 2023-10-26T12:36:27.956953: [INFO] Realm: Connection[1]: Session[1]: Integrated 1 changesets from pending bootstrap for query version 0, producing client version 10 in 1 ms. 0 changesets remaining in bootstrap
flutter:  >>> waitForDownLoad FINISHED. Amount of Items in the collection:  0
flutter: 2023-10-26T12:36:32.257177: [INFO] Realm: Connection[1]: Session[1]: Begin processing pending FLX bootstrap for query version 1. (changesets: 2, original total changeset size: 89509)
flutter: 2023-10-26T12:36:32.269323: [INFO] Realm: Connection[1]: Session[1]: Integrated 2 changesets from pending bootstrap for query version 1, producing client version 16 in 12 ms. 0 changesets remaining in bootstrap