react-native-firebase icon indicating copy to clipboard operation
react-native-firebase copied to clipboard

[🐛] removing secondary app listeners stops all projects listeners

Open moetezch opened this issue 2 years ago • 5 comments

Issue

  1. Create a secondary app ( or more)
  2. listen to a a similar path in the two apps
  3. remove listeners for the second app
  4. listeners stop working for the first app

import firebase from "@react-native-firebase/app"
import "@react-native-firebase/database"

   const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  databaseURL:"",
  projectId: "first-app",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
};

const firebaseConfig2 = {
  apiKey: "",
  authDomain: "",
  databaseURL:"",
  projectId: "second-app",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
};

// Initialize Firebase

const nodeRef = "users/be19e756-a51a-4f01-80fe-9a121c370957/cars";
firebase.initializeApp(firebaseConfig, { name: "first-app" });

firebase.initializeApp(firebaseConfig2, { name: "second-app" });

const app1Ins = firebase.app(firebaseConfig.projectId);
const app2Ins = firebase.app(firebaseConfig2.projectId);

app1Ins
  .database()
  .ref(nodeRef)
  .on("child_added", (snapshot) => {
    console.log("child_added", snapshot.val());
  });
app1Ins
  .database()
  .ref(nodeRef)
  .on("child_removed", (snapshot) => {
    console.log("child_removed", snapshot.val());
  });

app2Ins
  .database()
  .ref(nodeRef)
  .on("child_added", (snapshot) => {
    console.log("child_added", snapshot.val());
  });
app2Ins
  .database()
  .ref(nodeRef)
  .on("child_removed", (snapshot) => {
    console.log("child_removed", snapshot.val());
  });

setTimeout(() => {
  console.log("remove listeners");
  app2Ins.database().ref(nodeRef).off("child_added");
  app2Ins.database().ref(nodeRef).off("child_removed");
}, 5000);


Project Files

Javascript

Click To Expand

package.json:

{
  "main": "index.js",
  "scripts": {
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web",
    "start": "react-native start"
  },
  "dependencies": {
    "expo": "~43.0.2",
    "expo-splash-screen": "~0.13.5",
    "@react-native-firebase/app": "13.1.0",
    "@react-native-firebase/database": "13.1.0",
    "expo-status-bar": "~1.1.0",
    "expo-updates": "~0.10.13",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.3",
    "react-native-gesture-handler": "~1.10.2",
    "react-native-reanimated": "~2.2.0",
    "react-native-safe-area-context": "3.3.2",
    "react-native-screens": "~3.8.0",
    "react-native-web": "0.17.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9"
  },
  "private": true
}

firebase.json for react-native-firebase v6:

# N/A

iOS

Click To Expand

ios/Podfile:

  • [ ] I'm not using Pods
  • [x] I'm using Pods and my Podfile looks like:
# N/A

AppDelegate.m:

// N/A

Android

Click To Expand

Have you converted to AndroidX?

  • [ ] my application is an AndroidX application?
  • [ ] I am using android/gradle.settings jetifier=true for Android compatibility?
  • [ ] I am using the NPM package jetifier for react-native compatibility?

android/build.gradle:

// N/A

android/app/build.gradle:

// N/A

android/settings.gradle:

// N/A

MainApplication.java:

// N/A

AndroidManifest.xml:

<!-- N/A -->

Environment

Click To Expand

react-native info output:

 OUTPUT GOES HERE
  • Platform that you're experiencing the issue on:
    • [ ] iOS
    • [ ] Android
    • [ ] iOS but have not tested behavior on Android
    • [x] Android but have not tested behavior on iOS
    • [ ] Both
  • react-native-firebase version you're using that has this issue:
    • 13.1.0
    • 12.1.0
  • Firebase module(s) you're using that has the issue:
    • database
  • Are you using TypeScript?
    • N

moetezch avatar Dec 03 '21 17:12 moetezch

Interesting - nice work pointing it out via code, looks like a reasonably easy transfer to an e2e test to probe it with assertions and see the failure, the e2e tests do have access to a primary and secondary app for config + testing

both apps demonstrated usage https://github.com/invertase/react-native-firebase/blob/6a1125cad1bb79a169ca073cb7ddc12b467cc7ef/packages/database/e2e/database.e2e.js#L27-L33

example (among others) of probing child_removed events https://github.com/invertase/react-native-firebase/blob/6a1125cad1bb79a169ca073cb7ddc12b467cc7ef/packages/database/e2e/query/on.e2e.js#L196

First step is to make a test that fails (most of the work done via your sample combined with links here) then trace through while that code is "hot" (usually by making the test it.only so it's really focused) and usually the error is either very obvious, or it's in the native platform 😅

I won't have time to do this transform to test then examine for a while unfortunately, but that's the most efficient path forward if you have time to dig deeper

mikehardy avatar Dec 03 '21 17:12 mikehardy

thank you, sorry it took me some time to make the tests run. So I did a small change based on your advice , but I was just getting an error from the test helpers. I think I am missing something


  it.only('subscribe to child removed events', async function () {
    const successCallback = sinon.spy();
    const cancelCallback = sinon.spy();
    const ref = firebase.database().ref(`${TEST_PATH}/childRemoved`);
    const ref2 = firebase
      .database(firebase.app('secondaryFromNative'))
      .ref(`${TEST_PATH}/childRemoved`);

    ref2.off('child_removed');
    const child = ref.child('removeme');
    await child.set('foo');

    ref.on(
      'child_removed',
      $ => {
        successCallback($.val());
      },
      () => {
        cancelCallback();
      },
    );

    await child.remove();
    await Utils.spyToBeCalledOnceAsync(successCallback, 5000);
    ref.off('child_removed');
    successCallback.getCall(0).args[0].should.equal('foo');
    cancelCallback.should.be.callCount(0);
  });

Error :

moataz@moataz:~/Desktop/react-native-firebase$ yarn tests:android:test
yarn run v1.22.10
$ cd tests && ./node_modules/.bin/detox test --configuration android.emu.debug
detox[27098] INFO:  [test.js] mocha --config e2e/.mocharc.js --configuration android.emu.debug --grep :ios: --invert --use-custom-logger true e2e


detox[27110] INFO:  at node_modules/jet/lib/node/vm.js:78:11 
 [✈️] debugger has connected! Downloading app JS bundle...
detox[27110] INFO:  at node_modules/jet/lib/node/console.js:16:15 
 Mapping auth host "localhost" to "10.0.2.2" for android emulators. Use real IP on real devices. You can bypass this behaviour with "android_bypass_emulator_url_remap" flag.
detox[27110] INFO:  at node_modules/jet/lib/node/console.js:16:15 
 Mapping firestore host to "10.0.2.2" for android emulators. Use real IP on real devices. You can bypass this behaviour with "android_bypass_emulator_url_remap" flag.
detox[27110] INFO:  at node_modules/jet/lib/node/console.js:16:15 
 Mapping storage host to "10.0.2.2" for android emulators. Use real IP on real devices.
  database().ref().on()
detox[27110] INFO:  at node_modules/jet/lib/node/console.js:16:15 
 Running "testing" with {"rootTag":11}
detox[27110] INFO:  at e2e/init.js:40:15 
 
detox[27110] WARN:  at e2e/init.js:41:15 
 ⚠️ A test failed:
detox[27110] WARN:  at e2e/init.js:42:15 
 ️   ->  subscribe to child removed events
detox[27110] WARN:  at e2e/init.js:49:13 
 ️   ->  Retrying in 5 seconds ... (1)
    1) subscribe to child removed events

detox[27110] INFO:  at e2e/init.js:55:11 
  ✨ Tests Complete ✨ 
detox[27110] INFO:  at e2e/init.js:77:15 
 Coverage data downloaded to: ./android/app/build/output/coverage//emulator_coverage.ec

  0 passing (33s)
  1 failing

  1) database().ref().on()
       subscribe to child removed events:
     Error: Spy was not called within timeout period.
      at Timeout._onTimeout (/home/moataz/Desktop/react-native-firebase/tests/node_modules/@react-native-firebase/private-tests-helpers/lib/index.js:3:824)
      at listOnTimeout (node:internal/timers:557:17)
      at processTimers (node:internal/timers:500:7)



detox[27098] ERROR: [cli.js] Command failed: mocha --config e2e/.mocharc.js --configuration android.emu.debug --grep :ios: --invert --use-custom-logger true e2e

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Btw I tried the same code in the issue with firebase js sdk and it is working fine

moetezch avatar Dec 05 '21 22:12 moetezch

Oh that's fantastic that you have this open on your workbench. It can be a bit of a pain to get it all set up but there's nothing like a reproducible / automated test. You might just need to delay the check for the spy call? Sometimes the RTDB is slow, here's an example:

https://github.com/invertase/react-native-firebase/blob/6a1125cad1bb79a169ca073cb7ddc12b467cc7ef/packages/database/e2e/query/once.e2e.js#L125

Sadly I find it be a little flakier on the android emulator than iOS, so I prefer using iOS to develop against RTDB for listener stuff, however, that runs up against a second flaky issue we're having which is that Detox v18+ has a really nasty crash bug that kills the app maybe 20-40% of the time, making that not fun at the moment.

So I think adding a longer sleep would help ?

mikehardy avatar Dec 06 '21 01:12 mikehardy

sorry even when putting a longer sleep I was still getting the same error

 await Utils.spyToBeCalledOnceAsync(callback, 100000); 

also I couldn't make tests run on ios 😅

moetezch avatar Dec 12 '21 11:12 moetezch

Hello 👋, to help manage issues we automatically close stale issues. This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 18 '22 18:04 stale[bot]

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

github-actions[bot] avatar Dec 05 '22 19:12 github-actions[bot]

This one is perhaps still an issue and has what appears to be a reproduction

mikehardy avatar Dec 05 '22 21:12 mikehardy

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

github-actions[bot] avatar Jan 02 '23 23:01 github-actions[bot]