【问题标题】:How to abort a Firestore transaction in case of error发生错误时如何中止 Firestore 事务
【发布时间】:2019-01-29 17:04:06
【问题描述】:

我在 https 云函数(运行 Express)中使用 Firestore runTransaction 方法。 我想要的是确保如果任何读取或写入失败,其他事务读取或写入将不会运行或在需要时回滚。

交易

admin.firestore().runTransaction(async (t) => {
  const { uid, artworkUid, tagLabel } = req.body;

  if (!tagLabel) {
    return Promise.reject('Missing parameters: "tagLabel"');
  }

  if (!artworkUid) {
    return Promise.reject('Missing parameters: "artworkUid"');
  }

  if (tagLabel.length < 3) {
    return Promise.reject('The tag must be at least 3 characters long');
  }

  const [ user, artwork ] = await Promise.all([
    getUser(uid),
    getArtwork(artworkUid)
  ]);

  return Promise.all([
    addArtworkTag({
      artwork,
      tagLabel,
      proposer: user
    }, t),
    giveXpFor({
      user,
      action: 'add-artwork-tags',
      type: user.can('add-artwork-tags') ? 'effective' : 'temporary'
    }, t)
  ])
})
.catch(err => res.status(403).send(err))
.then(() => res.status(200).send());

如您所见,addArtworkTaggiveXpFor 函数采用 t in 参数。

添加艺术作品标签

export const addArtworkTag = function(params: { artwork: any, tagLabel: string, proposer: ShadraUser }, t?: FirebaseFirestore.Transaction): Promise<any> {
  const { artwork, tagLabel, proposer } = params;

  if (!artwork || !proposer || typeof tagLabel !== 'string') {
    return Promise.reject('Can\'t add the tag. Bad/missing datas');
  }

  const tag = <any>{
    slug: slugify(tagLabel),
    label: tagLabel,
    status: proposer.can('add-artwork-tags') ? 'validated' : 'proposed',
    proposerUid: proposer.uid
  };

  const tags = artwork.tags || [];
  tags.push(tag);

  const artworkRef = admin.firestore().doc(`artworks/${artwork.uid}`);

  t.set(artworkRef, { tags }, { merge: true });
  return Promise.resolve();
}

我的问题是:如果 addArtworkTag 函数失败(例如由于参数错误)我如何中止(甚至回滚)事务,以便不调用 giveXpFor

非常感谢

PS:我认为我滥用了事务......我应该做的可能只是使用顺序承诺而不是 Promise.all,对吧?

【问题讨论】:

    标签: firebase promise transactions google-cloud-firestore


    【解决方案1】:

    API documentation for runTransaction 声明:

    如果事务成功完成或被明确中止 (通过 updateFunction 返回一个失败的 Promise),Promise updateFunction 返回的将在此处返回。否则,如果 交易失败,一个被拒绝的 Promise 和相应的失败 将返回错误。

    您所要做的就是正确地返回一个被拒绝的承诺。您在该事务中做了什么并不重要 - 所有这些都将被回滚。

    【讨论】:

    • 就是这样。谢谢
    【解决方案2】:

    我不确定runTransaction 要使您的函数和查询更稳定,您应该多次使用以下命令来阻止整个脚本崩溃。

    try {
     //some code
    } catch (e) {
    
     //put code here to flag up issues with runTransaction
    
     console.error("Oh No, Not Again said the PlantPot", e);
    }
    

    https://firebase.google.com/docs/database/admin/save-data

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      • 2019-08-24
      • 2013-01-30
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      相关资源
      最近更新 更多