firebase-tools:
7.4.0
Platform:
Windows
Since auth is not available in the context for Firestore triggers, I send along some user data in the snapshot to log the activity and use the user token to create some extra steps inside the onCreate function. I extract the userdata from the snapshot and the want to remove the userdata using the snapshot.ref.set(snapShotWithoutUserData)
export const onOrganizerCreate = functions.firestore.document("organizers/{organizerId}")
.onCreate((snapshot, context) => {
return snapshot.ref.set({
test: "testing"
}, { merge: true });
})
I have tried ref.set(), ref.update() with or without the merge parameter, same result
Expect it to run without errors as it does when i deploy it.
The emulator/trigger crashes, giving this error
! Non-default "firebase-admin" instance created!
@ralcar thanks that's an interesting bug, I think I can see how it happened.
For now you can workaround this by doing:
const newRef = admin.firestore().doc(snapshot.ref.path);
return newRef.set({ ... });
This will construct a new reference using the emulated admin.firestore().
Note to self:
https://github.com/firebase/firebase-functions/blob/master/src/apps.ts#L107
I think we could get around this by initializing an app with the name __admin__ in the emulators as a way of tricking the firebase-functions library to use our mocks. It would be relying on an internal implementation detail but I don't see how it would be harmful.
Thank you for the quick answer, that worked great, thank you! Was worried i was going to have to build that path everywhere. This is cleaner, but I hope I could avoid importing the firebase-admin at all in the future ;).
Just for some more help with the debugging, i initializeApp on two different databases during bootup of the cloud functions. And i am locally on Node 10.15.1
@ralcar could you show the code where you initializeApp twice? It would be helpful so that I can recreate the situation.
I saw something similar using snapshot.ref.update() (also inside a trigger), which claimed the document didn't exist. Maybe related.
Weirdly enough though, snapshot.ref.set(doc, {merge: true}); worked without errors.
@larssn that sounds correct. .update() operations fail if the document does not exist. .set() operations create the document if it doesn't exist. set(data, { merge: true }) on a non-existent document is identical to set(data).
Sorry, I should have mentioned what kind of trigger it was, as it was the onCreate trigger.
The document should exist at that point I take it? In any case, it was easily solved using set.
@samtstern ofcourse, here it is!
My /functions/src/index.ts loads "main.ts" first, that looks like this:
import { config } from 'firebase-functions';
import { initializeApp, credential } from 'firebase-admin';
initializeApp(config().firebase);
const productionServiceAccount = require("../<production>.json");
const stagingServiceAccount = require("../<staging>.json");
initializeApp({
credential: credential.cert(productionServiceAccount),
databaseURL: "<url>"
}, "production");
initializeApp({
credential: credential.cert(stagingServiceAccount),
databaseURL: "<url>"
}, "staging");
export * from 'firebase-functions';
@ralcar thanks!
FYI initializeApp(config().firebase) is outdated, you should just use initializeApp() ... that doesn't change the bug here but it's worth noting.
@larssn yes the doc should definitely exist at this point. I worry that your code is talking to prod sometimes ... changing it to set() may have fixed the symptom but covered up the bug.
Working on this over here:
https://github.com/firebase/firebase-functions/pull/565
The fix for this issue has been released in version 7.6.0