3

I am having an issue dealing with multiple realms in React Native. I'm working on an app that allows users to use the app without having a subscription (using a local realm) and then at any point in their app journey they have the option of upgrading to a subscription with syncing (which uses sync to a realm object server).

When I start the app I check to see if they are using sync and if so I initialize a synced realm with their user and everything works great. I get all the data I expect.

However, when the app starts on first launch after install (that part about first launch after install is crucial) and I see that they don't use sync I initialize a local realm which I save data to until they decide to log in to their sync account (if they have one). At this point I attempt to pull information from the synced realm but it does not have the information that I saw when I only initialized the synced realm (in the case that on app startup I detect they use sync).

I am able to log in as the sync user but the data isn't there if I've previously initialized a local realm AND this logic gets run on the first launch of the app after install. The data only shows up from the realm object server when I initialize a local and synced realm on a secondary launch of the app (no reinstall before launching).

Here's a simple test script with dummy data in it with which I've been able to replicate the observed behavior:

const username = 'testuser2';
const password = 'supersecret';
const tld = 'REALM_OBJECT_SERVER_TLD';

class Test extends Realm.Object {}
Test.schema = {
  name: 'Test',
  properties: {
    id: {
      type: 'string',
    },
  }
};

function initLocalRealm() {
  return new Realm({
    path: 'local.realm',
    schema: [Test],
  });
}

function initSyncedRealmWithUser(user) {
  return new Realm({
    path: 'synced.realm',
    sync: {
      user,
      url: `realm://${tld}:9080/~/data`,
    },
    schema: [Test],
  });
}

function writeTestObjectWithId(realm, id) {
  realm.write(() => {
    realm.create('Test', {
      id,
    });
    alert(`Test object with id: ${id}`);
  });
}

initLocalRealm();

// setup
// uncomment this and comment out the login section to setup user on first run
// Realm.Sync.User.register(`http://${tld}:9080`, username, password, (error, user) => {
//   if (error) {
//     return;
//   }
//   const syncedRealm = initSyncedRealmWithUser(user);
//   writeTestObjectWithId(syncedRealm, '1');
// });

// login
Realm.Sync.User.login(`http://${tld}:9080`, username, password, (error, user) => {
  if (error) {
    return;
  }
  const syncedRealm = initSyncedRealmWithUser(user);
  alert(`Synced realm test objects: ${syncedRealm.objects('Test').length}`);
});

If you create a react native app and then add this code to the main components componentDidMount function you should see that on the first run of the app (after you've uncommented the register code once) you will see the Test collection length at 0, but then when you refresh you will see the Test collection length at 1.

Any help on this would be awesome.

Thanks!

jasonmerino
  • 3,220
  • 1
  • 21
  • 38
  • Just to be clear: you have two Realms with data in it, one synced and one local. When you open only the local one, you have data. When you open only the synced one, you have data. When you open both, you only have data in the local one, but the synced Realm is empty? – teotwaki Mar 03 '17 at 09:22
  • Correct. The only cases that I have so far are having only a local realm with data in it (which works as expected), having only a synced realm with data in it (which also works as expected), and then having a local realm which is initialized first and then a sycned realm which is initialized second and when I do this the synced realm never gets the data from the realm object server but the local realm still has it's data. I have not tried the other way yet (init synced first then local) but I have a suspicion that both realms will not get data then as well. – jasonmerino Mar 03 '17 at 13:23
  • Could you update your question with information on how you test that the synced Realm never gets data? Thanks. – teotwaki Mar 03 '17 at 13:28
  • @teotwaki I've narrowed it and added an updated code snippet with which you should be able to reproduce the problem I'm seeing. It seems that I do not get data back from the realm object server when initializing a local and then synced realm ONLY on first run after installing the app. If I just refresh the app I get the data back from the realm object server even with initializing a local then synced realm. – jasonmerino Mar 09 '17 at 20:36
  • Hey @teotwaki. I was curious if anyone on the realm-js team has had a chance to look into this. Any update? – jasonmerino Mar 14 '17 at 22:11
  • Sorry 'bout that. I'll have someone look at it tomorrow. – teotwaki Mar 14 '17 at 22:30
  • No worries. :) Thanks for the update! – jasonmerino Mar 14 '17 at 22:34

1 Answers1

0

running your code snippet, I get a length of 1 immediately as soon as I uncomment the login section. Could you try observing your synchronized realm with the Realm Browser and see if it seems to have the data you are expecting after registering the user?

Kristian Dupont
  • 800
  • 4
  • 12
  • When I pulled up the test user's path in Realm Browser I do see the data. I may not have explicitly said above that the React Native app needs to be rebuilt after running the code to register the user in order to see the behavior. Also, I'm running react-native 0.33.1 and realm 1.0.1 (I see that there are new versions out, I'll try the newest when I get a moment). Also, our current object server version is 1.0.2. – jasonmerino Mar 15 '17 at 12:36
  • I just tested with the realm NPM module version 1.1.1 and I'm seeing the same issue. It's probably worth it to note that in order to see this behavior I need to delete the app from the iOS simulator altogether. If I just re-run the app, or even stop the app in XCode then re-run it I get the correct number of objects coming back from the object server. – jasonmerino Mar 15 '17 at 12:44
  • Ah, so in that case you are probably simply asking before it's fully synchronized. We have an [issue](https://github.com/realm/realm-js/issues/794) for progress notification which is not yet implemented. Try adding a slight delay before you check. – Kristian Dupont Mar 15 '17 at 15:44
  • Okay, I think I came up with a solution. Directly after initializing my synced realm I added a bunch of listeners to it and then attempted to manually pull the data out of it for the initial population of my redux store. That made is so I was for sure going to get the data whenever it resolved. It seems to be working well now. – jasonmerino Mar 16 '17 at 20:04