Firestore 更新方法抛出错误:“错误:13 内部:收到代码为 1 的 RST_STREAM”

may*_*san 12 node.js grpc google-cloud-functions google-cloud-firestore

在使用云函数的过程中,我们遇到了以下错误:

时间戳:2023-10-21 18:50:18.281 EEST 功能:v8-specialist

---updateUserByID finish update---

Caused by: Error 
    at WriteBatch.commit (/workspace/node_modules/firebase-admin/node_modules/@google-cloud/firestore/build/src/write-batch.js:433:23) 
    at DocumentReference.update (/workspace/node_modules/firebase-admin/node_modules/@google-cloud/firestore/build/src/reference.js:433:14) 
    at Object.updateUserByID (/workspace/dist/src/DB/db.js:74:14) 
    at createSpecialistOrderListService (/workspace/dist/src/crud/specialist/services/specialistList/createSpecialistOrderListService.js:38:29) 
    at runMicrotasks (<anonymous>) 
    at processTicksAndRejections (node:internal/process/task_queues:96:5) 
    at async getRecommendedSpecialistsListController (/workspace/dist/src/crud/specialist/controllers/getRecommendedSpecialistsListController.js:25:44) 
    at async /workspace/dist/src/framework/express/middlewares/express-handler.js:18:36 

Error Details:
- Code: `13`
- Description: `Received RST_STREAM with code 1`
- Metadata: `{ internalRepr: Map(0) {}, options: {} }`
- Note: `Exception occurred in retry method that was not classified as transient`
Run Code Online (Sandbox Code Playgroud)

当我们在更新函数中执行以下命令时,似乎会弹出此错误:

const writeResult = await admin
      .firestore()
      .collection(FirestoreCollections.Users)
      .doc(userID)
      .update(fieldsToUpdate);
Run Code Online (Sandbox Code Playgroud)

示例fieldsToUpdate

const writeResult = await admin
      .firestore()
      .collection(FirestoreCollections.Users)
      .doc(userID)
      .update(fieldsToUpdate);
Run Code Online (Sandbox Code Playgroud)

然而,令人不解的是,这个方法在我们的其他云功能中似乎运行得完美无缺。在某些情况下,即使在更新过程中引发错误,Firestore 中的数据仍可能会更新。

  1. 即使在本地测试,该问题仍然存在。
  2. 用同样的方法创建一个新的云函数后,一切都运行顺利。

小智 4

上周我遇到了同样的问题,这似乎是 firebase / grpc 实现内部与 firebase 调用之间的长时间延迟相关的问题。

另外,firebase 库似乎正在远离 RPC,但如果您不设置,它仍然将其保留为默认选项preferRest: true请参阅文档

对我来说,当我在执行操作之前调用 init 或更改 firebase 配置以更喜欢使用休息通信时,它会起作用。

这是我的代码片段:

function getFbDb() {
  const mainFirebaseApp = firebaseAdmin.initializeApp({
      credential: firebaseAdmin.credential.applicationDefault()
    }, uuid.v4());

  const db = mainFirebaseApp.firestore();
  const settings = {
    preferRest: true,
    timestampsInSnapshots: true
  };
  db.settings(settings);
  return { db, firebaseApp: mainFirebaseApp };
}
const { db, firebaseApp } = getFbDb();
Run Code Online (Sandbox Code Playgroud)

const { db, firebaseApp } = getFbDb();每次必须执行操作时使用。

另一个“肮脏的选择”似乎是在第一次失败后使用重试方法。

如果这对您不起作用,请关注问题2345,看看会发生什么。