代码之家  ›  专栏  ›  技术社区  ›  DevMike

为什么我的Firebase Cloud函数中的事务无法检索存在的数据,从而失败?

  •  0
  • DevMike  · 技术社区  · 2 年前

    在我的第二代云功能中,我有以下代码:

    export const roomEnter = functions.https.onCall(async (request: any) => {
    
      // initial validation to verify user authentication and valid request data passes first
      ...
    
      const roomRef = admin.database().ref(`rooms/${request.data.roomId}`);
      const roomSnapshot = await roomRef.once("value");
      const testDataExists = {
        exists: roomSnapshot.exists(),
        data: roomSnapshot.val()
      };
      functions.logger.log("[room enter] CHECK ROOM EXISTS:", JSON.stringify(testDataExists));
    
      // In the logs, the data that exists DOES print to the console successfully
    
      const transactionRef = admin.database().ref(`rooms/${request.data.roomId}`);
      const transactionResult = await transactionRef.transaction((currentData) => {
        functions.logger.log("[room enter] Transaction current data:", JSON.stringify(currentData));
    
        // In the logs, `currentData` prints as `null`, why?
        // As a result, the transaction never gets beyond this condition and fails i assume after it has exhausted all internal retries
    
        if (currentData !== null) {
          if (currentData.memberTotal) {
            currentData.memberTotal += 1;
          } else {
            currentData.memberTotal = 1;
          }
          return currentData;
        } else {
          functions.logger.log("[room enter] Transaction needs to retry, room current data is null", {
            roomId: request.data.roomId
          });
          return; // Returning undefined should cause Firebase to retry the transaction
        }
      });
    
      if (transactionResult.committed) {
        // never able to reach this point
      } else {
        functions.logger.log("[room enter] transaction to increment member total failed");
        throw new functions.https.HttpsError("internal", "transaction to increment member total failed", {
          customData: {
            roomId: request.data.roomId
          }
        });
      }
    
      ...
    });
    

    测试 read 我在做交易之前只是作为一个测试来确认数据的存在。

    正如上面的代码注释中所指出的,尽管现有数据的引用路径已被确认存在,但事务仍会失败。

    除了尽可能记录错误之外,我不知道如何解决这个问题。

    我拥有的其他不使用事务的云功能可以毫无问题地读取和写入数据库。

    除了日志之外,我唯一的额外信息是,客户端将错误报告给客户端,作为500内部服务器错误以及包含消息的错误响应 transaction to increment member total failed

    关于我的数据库安全规则,作为一个测试,尽管这与我正确验证的管理员SDK无关,但我已经设置了 ".write": true 对于 rooms rooms/$roomId 以便将其排除为可能的原因。

    那么,为什么 currentData null 交易内部? 我还能做些什么来排除故障?

    1 回复  |  直到 2 年前
        1
  •  1
  •   Frank van Puffelen    2 年前

    Firebase实时数据库事务处理程序几乎总是使用 null 值,不管数据库中的实际值是多少。

    这是因为SDK会立即调用您的处理程序,并对当前值进行最佳猜测,而这通常是 无效的 。您的代码需要处理这种情况,以便SDK可以将null和新值发送到服务器,意识到其猜测是错误的,然后重试。

    这些年来,这已经被报道了好几次,在其中一些情况下可能比我在这里做的解释更好,所以我建议查看: