Firebase PITR使用报错求助:无效事务问题排查
Firestore PITR 测试报错:Invalid transaction
问题背景
我刚研究了新发布的**Point-in-time recovery (PITR)**功能,已按文档要求在Firebase项目中启用该功能,且使用npm最新版firebase-admin,但测试官方提供的PITR版本读取示例代码时失败,返回"Invalid transaction"错误。
测试代码
const documentRef = firestore.collection("users").doc("zqN5sVLtCSUkTJqmC64Nsv9mKYD2"); const preUpdate = 1691218778; const postUpdate = 1691226145; const timeToUse = preUpdate; const documentSnapshot = await firestore.runTransaction( updateFunction => updateFunction.get(documentRef), { readOnly: true, readTime: new Timestamp(timeToUse, 0) } ); console.log(`Email address at ${moment(timeToUse).format("DD/MM/YYYY HH:mm:ss")} was ${documentSnapshot.data().email}`)
错误信息
"error": { "code": 3, "details": "Invalid transaction.", "metadata": { "internalRepr": {}, "options": {} }, "note": "Exception occurred in retry method that was not classified as transient" }
解决方案
确认Timestamp正确导入
代码中使用的Timestamp必须从firebase-admin/firestore模块导入,否则创建的对象无法被Firestore识别:const { Timestamp } = require('firebase-admin/firestore');推荐使用
Timestamp.fromSeconds()方法构造时间戳,比直接传入秒和纳秒更直观:Timestamp.fromSeconds(timeToUse)单个文档读取无需使用事务
若仅读取单个文档的历史版本,无需使用事务,直接调用get方法并指定readTime参数即可,写法简洁且避免事务相关错误:const documentSnapshot = await documentRef.get({ readTime: Timestamp.fromSeconds(timeToUse) });事务方式的正确写法(多文档一致读取场景)
若需读取多个文档的同一时间点版本,必须用事务,但要确保事务选项和Timestamp对象都正确:const documentSnapshot = await firestore.runTransaction( (tx) => tx.get(documentRef), { readOnly: true, readTime: Timestamp.fromSeconds(timeToUse) } );检查时间戳是否在PITR保留窗口内
确认timeToUse对应的时间在PITR的保留期限内(默认7天,可在Firebase控制台修改),超出保留期的时间点无法读取。
内容的提问来源于stack exchange,提问作者Brandon Dooley
相关产品推荐
相关产品推荐

