LoginSignup
0
0

More than 1 year has passed since last update.

【Firebase】transaction中にFAILED_PRECONDITIONが発生した

Last updated at Posted at 2022-04-07

結論

複数の異なるリソースに対して、同時にtransaction.getすることはできない。

やろうとして失敗したこと

やりたかったことはこちら。

  • /teams/aaaドキュメントが存在することを確認
  • /users/xxxドキュメントが存在しないことを確認
  • /users/xxxドキュメントを新しく作成

こちらが問題のコード

index.ts
async createUser(): Promise<void> {
  const teamRef = doc(this.firestore, 'teams', 'aaa');
  const userRef = doc(this.firestore, 'users', 'xxx');
  await runTransaction(this.firestore, async (transaction) => {
    const teamDocSnap = await transaction.get(teamRef);
    if (!teamDocSnap.exists()) {
      throw new Error('チームが存在しません');
    }
    const userDocSnap = await transaction.get(userRef);
    if (userDocSnap.exists()) {
      throw new Error('すでにユーザーが存在しています');
    }
    transaction.set(userRef, {
      name: 'sample user name',
      teamId: 'aaa',
      createdAt: serverTimestamp(),
      updatedAt: serverTimestamp()
    });
  }).catch((err) => {
    console.log('transaction error', err);
  });
}

こちらを実行したところ、こんなエラーが発生してしまった。

9 FAILED_PRECONDITION: the stored version (1649289374616448) does not match the required base version (0)

原因と対処方法

まずかったのは、こちらの2行。

const teamDocSnap = await transaction.get(teamRef);
const userDocSnap = await transaction.get(userRef);

teamRefuserRefの異なる2つのリソースに対して、transaction.getを実行しようとしてしまった。
下のように、一方をgetDocにすることで対処した。

index.ts
async createUser(): Promise<void> {
  const teamRef = doc(this.firestore, 'teams', 'aaa');
  const userRef = doc(this.firestore, 'users', 'xxx');
  await runTransaction(this.firestore, async (transaction) => {
    const teamDocSnap = await transaction.get(teamRef);
    if (!teamDocSnap.exists()) {
      throw new Error('チームが存在しません');
    }
    const userDocSnap = await getDoc(userRef); // getDocに変更
    if (userDocSnap.exists()) {
      throw new Error('すでにユーザーが存在しています');
    }
    transaction.set(userRef, {
      name: 'sample user name',
      teamId: 'aaa',
      createdAt: serverTimestamp(),
      updatedAt: serverTimestamp()
    });
  }).catch((err) => {
    console.log('transaction error', err);
  });
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0