Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

collection.watch() fails on React Native SDK #3494

Closed
thehaiwave opened this issue Jan 6, 2021 · 14 comments · Fixed by #4155
Closed

collection.watch() fails on React Native SDK #3494

thehaiwave opened this issue Jan 6, 2021 · 14 comments · Fixed by #4155
Assignees

Comments

@thehaiwave
Copy link

thehaiwave commented Jan 6, 2021

Goals

I'm trying to monitor collection changes on a remote MongoDB Atlas database.

Expected Results

I followed the example on the official Realm docs to use the collection.watch() functionality for the RN SDK. The example works with Node, and it returns any newly inserted objects in the collection, which is what I'm going for. The exact same code, however, does not work in my RN project.

Actual Results

I get the following error message

EROR [TypeError: Invalid attempt to iterate non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.]

Steps to Reproduce

The error can be reproduced running the following code with the specified SDK and RN versions at the bottom. I call this function inside the componentDidMount() function, which looks like this:

componentDidMount() {
   this.watchMessageCollection().catch((err) => console.log('ERROR', err));
 }

And watchMessageCollection():

  async watchMessageCollection() {
    const {user} = this.props.session;
    const db = user.mongoClient('mongodb-atlas').db('main');
    const messages_collection = db.collection('chat_messages');
    const generator = messages_collection.watch();

    for await (const change of generator) {
      const {documentKey, fullDocument} = change;
      console.log(`new document: ${documentKey}`, fullDocument);
    }
  }

I tried running this function on different project files with the same result, so there's something about the generator itself that's off. The user auth works on my RN project, as do the database and collection connections.

Version of Realm and Tooling

  • Realm JS SDK Version: 10.1.2
  • Node: v15.1.0
  • React Native: 0.63.4
  • OS: Ubuntu 20.04.1 LTS
@kneth
Copy link
Contributor

kneth commented Jan 6, 2021

The watch implementation for React Native is unfortunately not stable. The reason is fetch implementation doesn't implement the entire spec (see facebook/react-native#27741). If possible, using sync might be better.

@thehaiwave
Copy link
Author

That is indeed unfortunate. Thank you for answering though, I'll start reading through the sync docs. Have a nice day!

@kraenhansen
Copy link
Member

I'll reopen this issue as a reminder for us to improve this. It might be as easy as applying the @react-native-community/fetch polyfill (via react-native-polyfill-globals).

@kraenhansen kraenhansen reopened this Jan 18, 2021
@ianpward
Copy link

ianpward commented Oct 6, 2021

Whats the estimate with the new polyfills implementation from RN?

@kneth
Copy link
Contributor

kneth commented Oct 26, 2021

Whats the estimate with the new polyfills implementation from RN?

My best estimate is one week. The actual implementation will not take long, but we will have to add some more testing to verify that it works as we expect.

@capt4ce
Copy link

capt4ce commented Nov 29, 2021

Hi @kneth, Is there any update regarding this?
Our team is planning to use Realm to trigger an operation when document is updated, so I think sync don't really serve the purpose for us.

@kneth
Copy link
Contributor

kneth commented Dec 3, 2021

After investigating the issue, we realized that it is required to enable the Babel plugin plugin-proposal-async-generator-functions in order to support async generators. But even with the plugin enabled, we still see issues with the fetch implementation. We continue the quest.

@kraenhansen
Copy link
Member

kraenhansen commented Dec 3, 2021

This was the source-code for the app we used to debug this:

import {useEffect} from 'react';
import Realm from 'realm';

import 'react-native-polyfill-globals/auto';

const app = Realm.App.getApp('realmjstestapp-jjhtf');
async function getUser() {
  await app.currentUser.logOut();
  if (app.currentUser) {
    return app.currentUser;
  } else {
    const credentials = Realm.Credentials.anonymous();
    return app.logIn(credentials);
  }
}

async function start() {
  const user = await getUser();
  console.log(user.id);
  const runs = user
    .mongoClient('mongodb-atlas')
    .db('watch-test-db')
    .collection('runs');
  console.log('Starting to watch!');
  for await (const run of runs.watch({})) {
    console.log('An event came in:', run);
  }
  console.log('Done watching!');
}

const App = () => {
  useEffect(() => {
    start().catch(console.error);
  }, []);
  return null;
};

export default App;

The observed behaviour is that the "Starting to watch!" message gets printed to the console but no event fires when changes happen to the documents on the server. Further investigations showed that the promise returned from the fetch inside of the realm-network-transport never resolves, pointing to an issue in React Native's fetch implementation, which might potentially be fixable using https://github.com/react-native-community/fetch (but this has not been verified).

@Arijit1809
Copy link

@kraenhansen still facing this issue despite installing the polyfills and the babel plugin, the generator throws an error saying its not iterable

@SipNWork
Copy link

SipNWork commented May 9, 2023

Still facing this issue after following all required steps.

@kneth
Copy link
Contributor

kneth commented May 9, 2023

@SipNWork

Did you add the two required poly fills?

  1. Polyfills for fetch, ReadableStream and TextDecoder: https://www.npmjs.com/package/react-native-polyfill-globals
  2. Babel plugin enabling async generator syntax: https://npmjs.com/package/@babel/plugin-proposal-async-generator-functions

@SipNWork
Copy link

SipNWork commented May 9, 2023

@SipNWork

Did you add the two required poly fills?

  1. Polyfills for fetch, ReadableStream and TextDecoder: https://www.npmjs.com/package/react-native-polyfill-globals
  2. Babel plugin enabling async generator syntax: https://npmjs.com/package/@babel/plugin-proposal-async-generator-functions

Working now after a small tweak but not returning any change on document insert. Throwing abort error after 2-3 minutes.
Mongodb Atlas showing failed requests on graph but not showing failed in logs.

@kraenhansen
Copy link
Member

kraenhansen commented May 10, 2023

@SipNWork can I get you to create another issue with the exact version of Realm JS you're using and ideally a small reproduction showing off the issue? If you have time it would also be great to hear if upgrading to Realm JS v12 (soon to be released as latest) helps solve the issue for you.

@SipNWork
Copy link

@SipNWork can I get you to create another issue with the exact version of Realm JS you're using and ideally a small reproduction showing off the issue? If you have time it would also be great to hear if upgrading to Realm JS v12 (soon to be released as latest) helps solve the issue for you.

Created a new issue for above
#5858

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants