realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.45k stars 1.75k forks source link

Opening a realm with initialSubscriptions while offline blocks its initialisation #7712

Open edualonso opened 1 year ago

edualonso commented 1 year ago

Opening a realm after having specified initialSubscriptions in the sync config while offline causes the initialisation to hang. We should be able to open a flexible sync enabled realm with subscriptions even if the device has no connectivity.

vikrantuk commented 1 year ago

Yes I faced the similar issue. Is there any workaround ?

edualonso commented 1 year ago

Hi @vikrantuk. Yes, there is. Calls to Application.currentUser() will return a valid user unless you log out once you are logged in. With this in mind you can assume your SyncConfiguration doesn't need to call initialSubscriptions since you should have already configured them when you logged in for the first time. This is the only viable workaround at the moment.

vikrantuk commented 1 year ago

@edualonso Thanks for responding. The problem is I'm using async method getInstanceAsync(config) which expects config to be passed and it might cause the same issue as config passed to Realm.setDefaultConfig has entry of intialSubscription passed into it. Please correct me if I'm wrong or misunderstood a thing or 2

edualonso commented 1 year ago

You should change the way you initialise your SyncConfiguration to avoid calling initialSubscriptions if your user is logged in and you have previously configured initial subscriptions. Something along these lines:

// ...
private void doStuff(User currentUser) {
    SyncConfiguration syncConfig;

    // Are we logged in?
    if (currentUser == null) {
        // log in and update your current user wherever you are storing it
        User loggedInUser = login();

        // first time creating the config: we are guaranteed to be online at this point so we need to add the initial subscriptions
        syncConfig = createConfig(loggedInUser, false);
    } else {
        syncConfig = createConfig(currentUser, true);
    }
    openRealm(syncConfig);
}

/**
 * @param user               current user.
 * @param previouslyLoggedIn if true means we have been online at some point, so no need to call 'initialSubscriptions' when creating the SyncConfiguration.
 */
private SyncConfiguration createConfig(User user, boolean previouslyLoggedIn) {
    SyncConfiguration.Builder builder = new SyncConfiguration.Builder(user);

    // add subscriptions in case we were not logged in, otherwise don't do it and allow using preexisting subscriptions from a time when the app was open and phone was online
    if (!previouslyLoggedIn) {
        builder.initialSubscriptions(new SyncConfiguration.InitialFlexibleSyncSubscriptions() {
            @Override
            public void configure(Realm realm, MutableSubscriptionSet subscriptions) {
                // add a subscription with a name
                Subscription mySubscription = subscriptions.find("MySubscription");

                if (mySubscription == null) {
                    RealmQuery subscriptionQuery = ...;
                    subscriptions.add(Subscription.create("MySubscription", subscriptionQuery));
                }

            }
        });
    }

    return builder.allowQueriesOnUiThread(true)
            .allowWritesOnUiThread(true)
            .build();
}

// ...

Please observe this will not work if you have not added initial subscriptions before introducing this change. You must have been able to add these subscriptions at a prior point in time.

vikrantuk commented 1 year ago

@edualonso Thanks.. I wasn't aware there is no need to set initialsubscriptions again. What I thought was running Realm.setDefaultConfig(config) again will overwrite the last set config and hence initialsubscription will also get wiped up. Thanks for the clarification :)

vikrantuk commented 1 year ago

Also are there resources where these minute things are covered. I had no idea about this from the documentation

edualonso commented 1 year ago

Hi @vikrantuk.

Also are there resources where these minute things are covered. I had no idea about this from the documentation

I'm afraid there aren't more resources than what's available in the official documentation. We will try to improve it to make it clearer in future modifications.

hkchakladar commented 7 months ago

@edualonso Using your avoid calling initialSubscriptions doesn't work if I initialise Realm in next activity without initialSubscriptions. Got this error:

Configurations cannot be different if used to open the same file.

Cached configuration:

realmDirectory: /data/user/0/com.in/files/mongodb-realm/application-0-vaocb/65566a52ab8ce3e71ebdcf22
realmFileName : default.realm
canonicalPath: /data/user/0/com.in/files/mongodb-realm/application-0-vaocb/65566a52ab8ce3e71ebdcf22/default.realm
key: [length: 0]
schemaVersion: 0
migration: null
deleteRealmIfMigrationNeeded: false
durability: FULL
schemaMediator: io.realm.DefaultRealmModuleMediator@41e1a0d
readOnly: false
compactOnLaunch: null
maxNumberOfActiveVersions: 9223372036854775807
serverUrl: wss://realm.mongodb.com/
user: io.realm.mongodb.User@346e449f
errorHandler: io.realm.mongodb.AppConfiguration$Builder$1@32b3670
initialSubscriptions: com.in.HomeActivity$1$1@2b60fa5
deleteRealmOnLogout: false
syncClientValidateSsl: true
serverCertificateAssetName: null
serverCertificateFilePath: null
waitForInitialData: false
initialDataTimeoutMillis: 9223372036854775807
sessionStopPolicy: AFTER_CHANGES_UPLOADED
syncUrlPrefix: /api/client/v2.0/app/application-0-vaocb/realm-sync
partitionValue: null

New configuration: 

realmDirectory: /data/user/0/com.in/files/mongodb-realm/application-0-vaocb/65566a52ab8ce3e71ebdcf22
realmFileName : default.realm
canonicalPath: /data/user/0/com.in/files/mongodb-realm/application-0-vaocb/65566a52ab8ce3e71ebdcf22/default.realm
key: [length: 0]
schemaVersion: 0
migration: null
deleteRealmIfMigrationNeeded: false
durability: FULL
schemaMediator: io.realm.DefaultRealmModuleMediator@41e1a0d
readOnly: false
compactOnLaunch: null
maxNumberOfActiveVersions: 9223372036854775807
serverUrl: wss://realm.mongodb.com/
user: io.realm.mongodb.User@346e449f
errorHandler: io.realm.mongodb.AppConfiguration$Builder$1@32b3670
initialSubscriptions: null
deleteRealmOnLogout: false
syncClientValidateSsl: true
serverCertificateAssetName: null
serverCertificateFilePath: null
waitForInitialData: false
initialDataTimeoutMillis: 9223372036854775807
sessionStopPolicy: AFTER_CHANGES_UPLOADED
syncUrlPrefix: /api/client/v2.0/app/application-0-vaocb/realm-sync
partitionValue: null