This is a rather involved question, but I’ll try to explain it as simply & concisely as I can…
I am using Firebase to build a multi-user, web-based game. I am keeping a list of every round in the game. At the end of a round, every user is presented with a “Start” button that they click when they are ready to begin the next round. The round begins when at least 50% of users have clicked “Start”.
I have a Firebase reference gameRef for the game, a reference roundListRef that represents the list of rounds, and a reference roundRef that represents the current round.
I have attached a child_added callback to roundListRef so that when a new round is added, it becomes everyone’s current round:
roundListRef.on('child_added', function(childSnapshot, prevChildName) {
roundRef = childSnapshot.ref();
});
I can track newRoundVotes and activePlayers, and calculate 50% easily from there. If 50% is reached, a new round is added, which triggers everyone’s child_added event and the new round will begin from there…
gameRef.child('newRoundVotes').on('value', function(snapshot) {
var newRoundVotes = snapshot.val();
gameRef.child('activePlayers').once('value', function(snapshot) {
var activePlayers = snapshot.val();
if (newDriveVotes / activePlayers >= 0.5)
addNewRound();
});
});
My questions is, how do I ensure that only one new round is added, and that everyone is on the same round?
For example, say there are 10 players and 4 have already voted to start the next round. If the 6th player votes before his child_added event is triggered from the 5th player, then a round will also be added for the 6th player.
The problem is similar to .set() vs .transaction(), but no quite the same (from my understanding).
Does anyone have a solution?
I think you can likely solve this with a transaction if the round names are known ahead of time. E.g. if you just use /round/0, /round/1, /round/2, etc.
Then you could have some code like:
Does this work for your scenario?