Облачная функция настроена на запуск при создании новой записи и проверяет, достаточно ли у нас игроков, чтобы начать игру. Если это так, он создает игру по адресу /matches
и записывает gameId
в запись каждого игрока, например: /users/{playerId}/profile/cm
Игроки слушают gameId
в своих записях базы данных, поэтому они знать, когда перейти к экрану GamePlay.
Поскольку много игроков одновременно запрашивают поиск противника, а облачная функция - это асинхронный параллелизм, возникают проблемы с параллелизмом, и, как вы можете видеть на картинке, пользователь добавлен в двух разных совпадениях.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.onNewRequest = functions.database.ref("/requests/{boardId}/{userId}").onCreate((change, context) => {
var boardId = context.params.boardId;
var createdUserId = context.params.boardId;
// new request created
var requests = admin.database().ref("/requests/"+boardId);
requests.once("value").then((requestsSnapshot)=>{
var waitersCount = requestsSnapshot.numChildren();
if(waitersCount > 1){
// more than one user waiting to join the game
// lets link users
var creatorSnapshot;
var guestSnapshot;
// more than two players waiting to play a game on the board{boardId}
var index = 0;
requestsSnapshot.forEach((childSnapshot) => {
if (index === 0) creatorSnapshot = childSnapshot;
if (index === 1) guestSnapshot = childSnapshot;
index++;
});
// we have the creator and the guest
// creatorSnapshot.key is the id of the user /requests/boardId/userId <<<<--
var match = admin.database().ref("/matches").push({
s: 1,
peers:{
[creatorSnapshot.key]:true,
[guestSnapshot.key]:true
}
});
match.then(()=>{
// delete waiters
admin.database().ref("/users/"+creatorSnapshot.key+"/profile/cm").set(match.key);
admin.database().ref("/users/"+guestSnapshot.key+"/profile/cm").set(match.key);
creatorSnapshot.ref.remove();
guestSnapshot.ref.remove();
return null;
}).catch((error) => {
console.log(error);
});
// var matchId = boardId + "-" + creatorSnapshot.key + "-" + guestSnapshot.key;
// return admin.database().ref("/matches/"+matchId).set({
// s: 1,
// peers:{
// [creatorSnapshot.key]:true,
// [guestSnapshot.key]:true
// }
// }).then(()=>{
// // delete waiters
// // creatorSnapshot.ref.remove();
// // guestSnapshot.ref.remove();
// return null;
// }).catch((error) => {
// console.log(error);
// });
}
return null;
}).catch((error) => {
console.log(error);
});
});