title: How to abort a Firestore transaction in case of error
body: <p>I'm using Firestore <code>runTransaction</code> method in a https Cloud function (running Express).
  What I want is ensure that if any of the read or write fails the other transaction reads or writes won't run or will rollback if needed.</p>
  
  <p><strong>Transaction</strong></p>
  
  <pre><code>admin.firestore().runTransaction(async (t) =&gt; {
    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 &lt; 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 =&gt; res.status(403).send(err))
  .then(() =&gt; res.status(200).send());
  </code></pre>
  
  <p>As you can see the <code>addArtworkTag</code> and <code>giveXpFor</code> functions take the <code>t</code> in parameter.</p>
  
  <p><strong>addArtworkTag</strong></p>
  
  <pre><code>export const addArtworkTag = function(params: { artwork: any, tagLabel: string, proposer: ShadraUser }, t?: FirebaseFirestore.Transaction): Promise&lt;any&gt; {
    const { artwork, tagLabel, proposer } = params;
  
    if (!artwork || !proposer || typeof tagLabel !== 'string') {
      return Promise.reject('Can\'t add the tag. Bad/missing datas');
    }
  
    const tag = &lt;any&gt;{
      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();
  }
  </code></pre>
  
  <p>My question is: If the <code>addArtworkTag</code> function fails (because of a bad parameter for instance) how can I abort (or even rollback) the transaction so <code>giveXpFor</code> is not called</p>
  
  <p>Thanks a lot</p>
  
  <p>PS: I think I've misused transactions... What I should do is probably just use sequential promises instead of Promise.all, right ?</p>