Having issues setting up Realm Sync

Hi, I have been trying to setup Realm Sync in a NodeJS IoT Application.

I have correctly connected to my database in my Atlas cluster and selected Partition Key as userId. Next my Permissions for both read and write are defined as:

{
  "%%partition": "%%partition"
}

My schema in the NodeJS client app is defined as:

export const AccelerometerReadingsSchema = {
  name: 'AccelerometerReadings',
  properties: {
    _id: 'objectId',
    userId: 'string',
    nodeId: 'string',
    readings: 'string[]',
    timestamp: 'date'
  },
  primaryKey: '_id'
};

Next openRealm and getRealm look like this:

async function openRealm(partitionKey: string): Promise<Realm> {
  const config = {
    schema: [AccelerometerReadingsSchema],
    sync: {
      user: users.getAuthedUser(),
      partitionValue: partitionKey
    }
  };
  return Realm.open(config);
}

export const getRealm = async (partitionKey: string) => {
  if (realms[partitionKey] == undefined) {
    realms[partitionKey] = openRealm(partitionKey);
  }
  return realms[partitionKey];
};

Then I simply write to the realm in my app:

const writeToRealm = async (
  userId: string,
  nodeId: string,
  readings: Array<string>,
  timestamp: Date
) => {
  const realm = await getRealm(`user=${users.getAuthedUser().id}`);
  let result;
  realm.write(() => {
    result = realm.create('AccelerometerReadings', {
      userId,
      nodeId,
      readings,
      timestamp
    });
  });
};

The app or the Realm logs show no errors, the app starts up fine, the user is properly logged in but the data is never written to MongoDB Atlas.

Any hints what I am doing wrong here?

@Sheikh_Muhammad_Umar Is it possible that your users.getAuthedUser() is returning an unresolved promise?

Hello Andrew, thank you for the response.

EDIT On another note console.log by design logs Realm objects in this way. https://github.com/realm/realm-js/issues/2758. If I use getAuthedUser().id it prints the correct id for the currently logged in user. So to answer your original comment its not returning an unresolved promise.

You are correct, it looks like an empty User is returned when calling users.getAuthedUser(). But I am trying to figure out why. I have a users.ts file and I have pretty much set it up like MongoDB has provided the structure in the NodeJS tutorial for Realm.

const app = new Realm.App(appConfig);

const email = process.env.EMAIL_ADDRESS
const password = process.env.PASSWORD

export const login = async () => {
  try {
    const credentials = Realm.Credentials.emailPassword(email, password);
    const user = await app.logIn(credentials);
    if (user) {
      output.result("You have successfully logged in as " + app.currentUser.id);
    } else {
      output.result("There was an error logging you in");
    }
  } catch (err) {
    output.error('Login failed', `${err.message}`);
  }
};

export const getAuthedUser = () => {
  console.log(app)
  return app.currentUser;
};

When the app starts in the index.ts file I call login and the console successfully prints out You have successfully logged in as 613f20e657d2377e64157b12. But when getAuthedUser() is called later when I am actually trying to write to realm, User is an empty object, also App is an empty object printed like this:

App {}

User {}

It’s normal that App and User show an empty object when logged. We should probably setup some useful enumerated values there, but I digress. What I’m curious of is if the partition string is correctly propagated to the sync server. Can you make a log of that before calling getRealm?

Yes, I believe it is being propagated to the sync properly. I am using this to getRealm:

console.log(users.getAuthedUser().id);
const realm = await getRealm(`${users.getAuthedUser().id}`);

The app console properly shows the current user’s id and I get

Logs:
[
  "Client bootstrap completed in 214.050019ms. Received 1 download(s) containing 1 changeset(s) (195 bytes total)."
]
Partition:

613f20e657d2377e64157b12

in the Realm Logs on Atlas, if I use

const realm = await getRealm(`user=${users.getAuthedUser().id}`);

I get a PermissionDenied Error in the Logs.

I have terminated and re-enabled Sync as well because I was skeptical about my previous permissions for Read and Write.
Now they are:

{
  "%%partition": "%%user.id"
}

The Logs now possibly show that the client is attempting to Sync with Atlas but still the actual collection has NO documents.

Can you change the log level of Sync? Perhaps that will show more insight into what is going wrong here:

Realm.App.Sync.setLogLevel(myApp, "all");

I have set Log Level to all and I cant find any red flags or issues. The best I can figure out is that there is some issue with the openRealm function:

async function openRealm(partitionKey: string): Promise<Realm> {
  const config = {
    schema: [AccelerometerReadingsSchema],
    sync: {
      user: users.getAuthedUser(),
      partitionValue: partitionKey
    }
  };
  console.log(users.getAuthedUser().id)
  return Realm.open(config);
}

getRealm calls this and it returns a completely empty object against the partition string.

export const getRealm = async (partitionKey: string) => {
  if (realms[partitionKey] === undefined) {
    output.result("OPEN NEW REALM")
    realms[partitionKey] = openRealm(partitionKey);
  }
  output.result(`Realms: ${JSON.stringify(realms)}`)
  return realms[partitionKey];
};

Output:

OPEN NEW REALM
Realms: {"613f20e657d2377e64157b12":{}}

Some of the last lines from Realm app log are:

Connection[1]: Session[1]: Progress handler called, downloaded = 172, downloadable(total) = 172, uploaded = 0, uploadable = 0, reliable_download_progress = true, snapshot version = 20
Connection[1]: Session[1]: Received: MARK(request_ident=2)
Connection[1]: Session[1]: Sending: UPLOAD(progress_client_version=20, progress_server_version=1, locked_server_version=1, num_changesets=0)
Connection[1]: Sending: PING(timestamp=169702877, rtt=0)
Connection[1]: Received: PONG(timestamp=169702877)
Connection[1]: Round trip time was 683 milliseconds
Connection[1]: Will emit a ping in 58615 milliseconds

Could it be a permissions issue?
Have you applied the “Users can only read and write their own data” template?

Yes, this is exactly what I did. I have tried everything that I can think of and it still refuses to sync with Atlas. The main thing is there are no errors or even warnings that something is wrong

Is the userId you are sending to writeToRealm the same as the userId for getAuthedUser()?

Yes, just double checked it as well right now.

What happens if after the write, you do await realm.syncSession.uploadAllLocalChanges()?

Hello Andrew, thanks for your help but I have added this uploadAllLocalChanges() but nothing changed. Still the same issue. No errors, no warnings and no Syncing with Atlas.

I think we aren’t going to get any further without actually running some sample code. Can you make us a repo on github that produces this issues so we can reproduce it?

Hello Andrew, thanks for all the help. I have created a new project on Github that demonstrate the issues with my approach.

1 Like

I have been able to run and sync with Mongodb Atlas now with the latest updated code on this repository. Let me check if I can get my existing code to synchronize now.

If it works, feel free to share what the fix was, so that others in the forum can learn from you :slight_smile:

1 Like