Check when syncing is done

cloud
ros
platform

#1

Simple task: check if a user with an email exists.

In an app with a Rest api server, this could be function that returns true/false, no network or error.

To do this in realm cloud, from what I have read, I have to deal with a “one time” subscription (please correct me if I’m wrong).

I’m trying the following (Swift):

query = realm.objects(User.self).filter("email = '\(email)'")
subscription = query.subscribe()
token = subscription.observe(\.state) { [weak self] state in
            switch state {
            case .complete:
                if self.query.count == 0 {
                    completion("Doesn't exist, you can sign up")
                } else {
                    completion("Exists, you can't use this email")
                }
                self.subscription?.unsubscribe()
            case .error:
                completion("Error")
                self.subscription?.unsubscribe()
            default: break
            }
        }
    }

I found 2 issues with this:

  1. If I don’t have network connection, the state stays as “.pending” until connection resumes, but I want this call to complete asap. If I don’t have connection, I want to complete with a “no connection” error asap, and if it fails for another reason, just complete with an unknown error. Is there a realm-way to do this?

  2. If I call this function once and succeeds, but I don’t unsubscribe, and then I put airplane mode and call this function again, I receive a “.complete”, returning the same info as before… that can be misleading as data could have changed in the server. A flag to know if everything is up to date would be useful for this maybe, I tried with addProgressNotification, but it’s being called when transfers complete, but not when there are connection issues.

  3. Bonus question: I’m in the need of a flag to know, in a given moment, if everything is “up to date” with the server, or “is syncing”, or “no network connection” (or “sync is pending”), to show to the user in a label. Is there an easy way do this? This may also help for question 2.


#2

@chris32786 It looks like you are trying to use query-based sync as a drop-in replacement for a GET request with a query but realm sync is different because it persists data to disk. Query-based sync is just a method for populating this local cache of data in realm. Unless it’s just way too much data, I would just subscribe to all of the users and do local queries perhaps via a full sync global or common realm. If it is way too much data, probably contort the data model to make it so that the relevant subset is a reasonable size. Take a look at our different realms writeup here - https://docs.realm.io/sync/using-synced-realms/designing-an-architecture-with-multiple-realms

the bonus question is actually a lot easier: observing the connectionState property of the session plus a download progress notification will tell them if it’s disconnected, currently updating, or up-to-date


#3

Thanks @ianward.

I’m using a query based sync realm. I don’t like to sync all users, I find it a bad practice to sync all users of the app into the client, it’s low performant and not very secure. And I don’t see a way to subset users for this case, is just a search by email in ALL users.

The approach I’m presenting has more sense to me, to query and then just dispose the subscription, but idk. I will try to figure out to make it work correctly, but I find this disappointing, it’s just a basic task… :worried:


#4

Same pain here.
It’s completely unclear how to use Realm properly. Query-based sync sounds like the best option, but I’m personally struggle with it. And yes, drop-in for GET request seems to be the only sane way of updating specific record.
Let’s say I’m building real-time application (similar to what you guys had in example for drawing application) - there’s no way we can use load everything and once stay happy - records are constantly changing and we need to show most relevant info


#5

@Blackening @chris32786 We are adding the ability for the retrieveAccount API to now be queried by non-admins - there is security concerns but you can choose to add this option if you wish. stay tuned

the PR is up below -

Added an option to AuthService called allowAnyUserToRetrieveUserInfo that enables any registered user to call the
GET /auth/users/:user_id and GET /auth/users/:provider/:provider_id HTTP APIs, either directly or with SDK methods
such as the JavaScript SDK’s Realm.Sync.User.retrieveAccount method.


#6

Thanks @ianward. But this is only by user? Mine was just an example, but it could be for any entity and for any attribute/s. I need this for many quick search queries. And also, I have to implement a rest api for this solution…

I will try to make disposable queries work, when I have the time, and I let you know how well it works.


#7

@chris32786 correct this is just for the SyncUser that are realm specific and internal to our system. My response on Jan28 still stands - realm sync is not just a drop-in replacement for REST, we are optimized for offline-first and the subscriptions are used to create that local state to enable offline-use.

As you say,

Then I would suggest restricting the objects a user should have access to via a server-side admin app that restricts access with our fine-grained permissions API
https://docs.realm.io/sync/using-synced-realms/access-control/fine-grained-permissions


#8

@ianward @Blackening Hi guys, I worked a bit on this over the weekend and created a set of classes which I uploaded to GitHub: https://github.com/ceichin/RealmSyncHelpers

I basically address some of the problems presented in this thread using a DisposableSyncQuery and a SyncManager.

DisposableSyncQuery handles quick “one time” subscriptions safely. And SyncHandler helps me to check the Realm sync status (“synced”, “syncing” or “not synced”).

I added a brief explanation and attached a gif example to the readme. I’m open to suggestions/comments :slight_smile: , I will keep working on this over the weeks when I find some time.


#9

@chris32786 we have a PR up that implements some of this same functionality here -