0

I would like a function to get executed everytime a new user is added to a matchmaking object, to increase the number of matchmaking users.

exports.onCreateMatchmakingUser = functions.database.ref('/matchmaking/{$uid}').onCreate((snapshot, context) => {
    const currentMatchmakingAmount = snapshot.ref.parent.child('matchmakingAmount').val();
    return snapshot.ref.parent.update({matchmakingAmount: currentMatchmakingAmount+1});
});

I don't want to fetch the whole matchmaking object and then fetch the number, I just want the matchmakingAmount. Does snapshot.ref.parent make this a problem (does it fetch the whole matchmaking object, or just the reference to it without downloading its data)? And if it does, how can I solve this problem and write another function that just updates the number without unnecessary downloads?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
DaddyMike
  • 161
  • 11

1 Answers1

0

The snapshot.ref.parent.child('matchmakingAmount') in your code doesn't read anything from the database. Instead, it merely sets up a reference to the matchmakingAmount in the database. You'll still need to explicitly read it with once("value"):

let amountRef = snapshot.ref.parent.child('matchmakingAmount');
return amountRef.once("value").then((amount) => {
  let currentMatchmakingAmount = amount.val();
  return amountRef.set(currentMatchmakingAmount+1});
});

Luckily there is nowadays a simpler way to do this, as Firebase has a built-in increment operator. With that, the above boils down to:

let amountRef = snapshot.ref.parent.child('matchmakingAmount');
amountRef.set(admin.database.ServerValue.increment(1));

This approach also solves the race condition that exists in your approach: if two people trigger the Cloud Function at almost the same time, the two writes may get into each other's way. By using a server-side increment that won't happen.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • When implementing the second bit of code you've written, should I also return amountRef.set(admin.database.ServerValue.increment(1)); since set returns a promise? – DaddyMike Nov 11 '20 at 21:47
  • Yup. Since the write is asynchronous, you want to Cloud Function to remain alive until it completes and for that you need to return the promise to the container. – Frank van Puffelen Nov 11 '20 at 23:41