Reputation: 532
I have a database triggered function, that triggers when a team administrator adds new members to his team. The function is supposed to create authentication in Firebase and an object, where the new user can store his personal settings. My problem is, that when a lot of members are added simultaneously via an import feature, my function doesn't always complete. Since they seem to be triggered alright when I look at the log, I suspect my implementation of chained promises to be the error cause. Here is a copy of the code. Please help me correct the errors.
// When a team adds a new member, we should also create authentication and a record for his user data...
exports.createNewUserAndAuthOnNewMember = functions
.database
.ref('/Members/{team}/{memberId}/createNewUser')
.onCreate(event => {
const memberRef = admin.database().ref('/Members/'+event.params.team+'/'+event.params.memberId);
memberRef.once('value')
.then((memberSnap) => {
const memberEmail = memberSnap.child('email').val();
const preferredLanguage = memberSnap.child('preferredLanguage').val();
// Creating authentication for new system user...
//since we want to update the /user object later on even if the authentication creation fails (because user already exists), this promise is inside the top promise chain
admin.auth().createUser({
uid: event.params.memberId,
email: memberEmail,
emailVerified: false,
password: '[random password generated]',
disabled: false
})
.then(function(userRecord) {
console.log("Successfully created new user:", userRecord.uid);
return preferredLanguage;
})
.catch(function(error) {
console.log("Error creating new user:", error);
return preferredLanguage;
});
})
.then(preferredLanguage => {
// Creating the personal user object in the database
admin.database().ref('/users/'+event.params.memberId).update({'team': event.params.team, 'preferredLanguage': preferredLanguage});
})
.then(() => {
//we did the job and should remove the trigger from the member object in the database
memberRef.child('createNewUser').remove();
})
.then(() => {
console.log('Created /users/'+event.params.memberId);
return true;
});
});
Upvotes: 0
Views: 327
Reputation: 83093
This should work:
exports.createNewUserAndAuthOnNewMember = functions
.database
.ref('/Members/{team}/{memberId}/createNewUser')
.onCreate(event => {
let preferredLanguage;
const memberRef = admin.database().ref('/Members/' + event.params.team + '/' + event.params.memberId);
return memberRef.once('value')
.then((memberSnap) => {
const memberEmail = memberSnap.child('email').val();
preferredLanguage = memberSnap.child('preferredLanguage').val();
// Creating authentication for new system user...
//since we want to update the /user object later on even if the authentication creation fails (because user already exists), this promise is inside the top promise chain
return admin.auth().createUser({
uid: event.params.memberId,
email: memberEmail,
emailVerified: false,
password: '[random password generated]',
disabled: false
})
})
.then(() => {
// Creating the personal user object in the database
return admin.database().ref('/users/' + event.params.memberId).update({'team': event.params.team, 'preferredLanguage': preferredLanguage});
})
.then(() => {
//we did the job and should remove the trigger from the member object in the database
return memberRef.child('createNewUser').remove();
})
.catch(error => {
console.log(error);
//...
});
});
You have to return the promise in each then()
when chaining them, and you only need one catch at the end of the chain.
In addition, note that you are using the "old" syntax for Cloud Functions. Since version 1.0.+ there is a new syntax, see https://firebase.google.com/docs/functions/beta-v1-diff
Upvotes: 1