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

Can't use multiple RTDB instances with emulator #3681

Closed
rhodgkins opened this issue Aug 25, 2020 · 2 comments · Fixed by #4247
Closed

Can't use multiple RTDB instances with emulator #3681

rhodgkins opened this issue Aug 25, 2020 · 2 comments · Fixed by #4247
Assignees

Comments

@rhodgkins
Copy link
Contributor

rhodgkins commented Aug 25, 2020

[REQUIRED] Describe your environment

  • Operating System version: macOS 10.15.6 (19G73)
  • firebase-admin SDK version: 9.1.1
  • firebase-tools version: 8.9.0
  • @firebase/database version: 0.6.11
  • RTDB emulator version: 4.5.0
  • Firebase Product: database, testing-sdk
  • Node.js version: 14.8.0

[REQUIRED] Describe the problem

When using multiple database instances (via app.database(URL)) with the firebase-tools emulator errors are thrown.

Steps to reproduce:

const { app } = require('firebase-admin')

const _app = require('firebase-admin').initializeApp({
   databaseURL: 'https://against-emulator.firebaseio.com'
})

Promise.resolve(_app).then(async app => {
   const mainInstance = app.database()
   console.log('Main DB:', mainInstance['repo_']['repoInfo_'])
   const mainInstanceRef = mainInstance.ref('root')
   console.log('Main DB ref:', mainInstanceRef.toString())
   const otherInstance = app.database('https://against-emulator-other-instance.firebaseio.com')
   console.log('Other DB:', otherInstance['repo_']['repoInfo_'])
   const otherInstanceRef = otherInstance.ref('root')
   console.log('Other DB ref:', otherInstanceRef.toString())
})
   .catch(err => console.error('Error - ', err))
   .finally(() => _app.delete())

Run the above code with just node script.js and the following is outputted with no errors:

Main DB: RepoInfo {
  secure: true,
  namespace: 'against-emulator',
  webSocketOnly: false,
  persistenceKey: '',
  includeNamespaceInQueryParams: false,
  host: 'against-emulator.firebaseio.com',
  domain: 'firebaseio.com',
  internalHost: 'against-emulator.firebaseio.com'
}
Main DB ref: https://against-emulator.firebaseio.com/root
Other DB: RepoInfo {
  secure: true,
  namespace: 'against-emulator-other-instance',
  webSocketOnly: false,
  persistenceKey: '',
  includeNamespaceInQueryParams: false,
  host: 'against-emulator-other-instance.firebaseio.com',
  domain: 'firebaseio.com',
  internalHost: 'against-emulator-other-instance.firebaseio.com'
}
Other DB ref: https://against-emulator-other-instance.firebaseio.com/root

Now running against the DB emulator firebase emulators:exec --project against-emulator --only database 'node script.js', errors occur:

Main DB: RepoInfo {
  secure: false,
  namespace: 'against-emulator',
  webSocketOnly: false,
  persistenceKey: '',
  includeNamespaceInQueryParams: true,
  host: 'localhost:9000',
  domain: 'localhost:9000',
  internalHost: 'localhost:9000'
}
Main DB ref: http://localhost:9000/root
[2020-08-25T13:22:27.260Z]  @firebase/database: FIREBASE FATAL ERROR: Database initialized multiple times. Please make sure the format of the database URL matches with each database() call. 
Error -  Error: FIREBASE FATAL ERROR: Database initialized multiple times. Please make sure the format of the database URL matches with each database() call. 
    at fatal (<path>/node_modules/@firebase/database/dist/index.node.cjs.js:341:11)
    at RepoManager.createRepo (<path>/node_modules/@firebase/database/dist/index.node.cjs.js:15047:13)
    at RepoManager.databaseFromApp (<path>/node_modules/@firebase/database/dist/index.node.cjs.js:15014:25)
    at Object.initStandalone (<path>/node_modules/@firebase/database/dist/index.node.cjs.js:15389:45)
    at DatabaseService.getDatabase (<path>/node_modules/firebase-admin/lib/database/database-internal.js:82:23)
    at FirebaseApp.database (<path>/node_modules/firebase-admin/lib/firebase-app.js:232:24)
    at <path>/script.js:12:30

Relevant Code:

This is the bit of code throwing the error:

let repo = safeGet(appRepos, repoInfo.toURLString());
if (repo) {
fatal(
'Database initialized multiple times. Please make sure the format of the database URL matches with each database() call.'
);
}

It seems that RepoInfo#toURLString:

toURLString(): string {
return (this.secure ? 'https://' : 'http://') + this.host;
}

Doesn't take into account the namespace of the RepoInfo which the emulator uses to distinguish between different DB instances.

@rhodgkins
Copy link
Contributor Author

Happy to do a PR which updates RepoInfo#toURLString to include a namespace if one is present if this is the correct fix for this issue! LMK

@samtstern
Copy link
Contributor

@rhodgkins thank you for filing such a detailed issue! Sorry nobody ever answered you at the time. I think you've diagnosed the problem correctly, I will put together a PR today based on your suggestion.

@samtstern samtstern self-assigned this Dec 29, 2020
@firebase firebase locked and limited conversation to collaborators Jan 30, 2021
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.

3 participants