0

我正在借助实时数据库制作 1 对 1 游戏匹配系统。当用户登录时,它会在用户表中生成一条记录。当有 2 名玩家用户状态为占位符时,云功能将为这 2 名玩家生成一个游戏信息并将他们的用户状态更改为等待。我正在做的是创建一个触发函数来观察用户/{uid},当它的状态子是占位符时,然后调用 matchmaker 函数以生成具有唯一 gameId 的 gameInfo。但问题是当触发器 onWrite 函数第一次运行时,理论上只有一个具有占位符状态的用户,但是在某些情况下,当迭代数据库用户表时,数据库变化如此之快,它有两个具有占位符状态的玩家。所以有时会发生一些有线的事情,在两次触发函数回调之后,gameInfo 中应该只有一个 gameId 记录,因为两个玩家以唯一的 gameId 加入一个游戏房间,但有时会生成两个唯一的 gameId 记录。我怎样才能避免这种有线的事情发生。这是数据库表。 数据库表

这是我的云功能代码的一部分。对于matchmaker函数,如果地图中有两个玩家waitingPlayers,它会在games表中生成gameId记录。

export const searchWaitingPlayers = functions.database.ref("users/{uid}").onWrite( (change, context) => {
  if (!change.after.exists()) {
    console.log("uid deleted");
    return null;
  } else {
    if (change.after.child("status").val() !== "placeholder") {
      console.log("user's status is not placeholder");
      waitingPlayers.delete(change.after.key);
    } else {
      waitingPlayers.clear();
      admin.database().ref("users").once("value").then(async (users) => {
        users.forEach((user) => {
          if (user.child("status").val() === "placeholder") {
            waitingPlayers.set(user.key, user.child("username").val());
          }
        });
        matchmaker();
      });
    }
    return null;
  }
});
4

2 回答 2

0

如果不删除它,就无法以编程方式禁用云功能。但是,一种解决方案是使用功能标志来确定云功能是否执行其主要功能。为此可以参考以下代码。

exports.onUpload = functions.database 
.ref("/uploads/{uploadId}") 
.onWrite((event) => { 
return ifEnabled("transcribe").then(() => {
console.log("transcription is enabled: calling Cloud Speech");
            ... 
 })
});

ifEnabled 是一个简单的辅助函数,用于检查(也在实时数据库中)是否启用了该功能:

function ifEnabled(feature) { 
console.log("Checking if feature '"+feature+"' is enabled"); 
return new Promise((resolve, reject) => { 
   admin.database().ref("/config/features")
     .child(feature) 
                  .once('value') 
     .then(snapshot => { 
        if (snapshot.val()) { 
        resolve(snapshot.val()); 
    } else
      { 
      reject("No value or 'falsy' value found"); 
      }
   });
 });
}
于 2021-11-01T10:44:40.813 回答
0

我不确定您的问题何时发生,但在数据发生的两次更新之间似乎存在某种竞争条件。

为了防止数据更新的竞争条件,您需要使用事务

于 2021-10-29T14:26:09.203 回答