前提・実現したいこと
申請に対して、現在の申請数をチェックし、制限人数以内なら許可、オーバーする場合は不許可を返す関数を作りたいです。
firebaseを使っているため、トランザクションを活用し、上記の関数を作ろうとしているのですが、上手くいきません。
正確には、殆どの場合上手くいくのですが、時々カウントと実際の申請許可数がずれてしまいます。
なにかトランザクションの仕様を見落としているのでしょうか。
コードを見て頂き、見落としている点や原因を絞り込む方法があれば教えて頂きたいです。
データベース構造と起きている現象
コレクション:Number
ドキュメント:id
フィールド:
・max:Int(制限人数)
・number: Int(現在の申請許可数)
申請が4件しか来ていないのに、numberが6になっていることがあります。
Maxを6に設定してた場合、4件しか申請を許可していなのに、申請の許可が止まるため困っています。
毎回ではないのですが、たまに数字がズレ、再現しようとしても条件が分かりません。
該当のソースコード
Javascript
1exports.numberSet = functions.region(REGION).https 2 .onCall(async(data, context) => { 3 4 const numberRef = db.collection("Number").doc(//id); 5 6 try { 7 const withinCapacity = await db.runTransaction(async(transaction) => { 8 const numDoc = await transaction.get(numberRef) 9 if (!numDoc.exists) { 10 throw "Document does not exist!" 11 } 12 const newNumber = numDoc.data().number + 1 13 const max = numDoc.data().max 14 15 if (!Number.isFinite(max) || newNumber <= max) { 16 transaction.update(numberRef, { number: newNumber }) 17 return true 18 } else { 19 return false 20 } 21 }) 22 if (withinCapacity) { 23 return true 24 } else { 25 return false 26 } 27 28 } catch (error) { 29 return error 30 } 31 })
試したこと
いろんな条件で関数を動かしてみても、再現ができません。(正しくカウントしてくれます)
しかし、複数人の友達に触って貰ってみると、たまに数字がずれてエラーを取得できないでいます。
補足情報(FW/ツールのバージョンなど)
関数はcloud Functionで動かしています。
関数を呼び出す申請フォームを友達に触ってもらってみたところ、記載の現象が起きています。
修正依頼を受けての追記
申請と言っても、定員数以内かどうかだけをチェックして、定員数以内ならその場で自動的に許可&クライアント側に許可されましたとその場で表示する仕様です。
定員オーバーなら、falseを返し、その場で定員オーバーと表示されます。
申請フォームを作った人が、手動で許可するといったものではありません
そのため、質問に記載したコードの下記の部分(定員以内の場合の挙動)以外でnumberを+1することはありません。
transaction.update(numberRef, { number: newNumber })
numberを-1することはあるので、質問のコードに追加しておきます
numberを-1するのは、キャンセルが生じた場合です
Javascript
1exports.cancelSet = functions.region(REGION).https 2 .onCall(async(data, context) => { 3 4 const numberRef = db.collection("Number").doc(//id); 5 6 try { 7 return db.runTransaction(async(transaction) => { 8 const numDoc = await transaction.get(numberRef) 9 if (!numDoc.exists) { 10 throw "Document does not exist!" 11 } 12 var newNumber = numDoc.data().number - 1 13 transaction.update(numberRef, { number: newNumber }) 14 }).then(() => { 15 return true 16 }).catch((error) => { 17 return false 18 }); 19 } catch (error) { 20 return error 21 } 22 })
回答1件
あなたの回答
tips
プレビュー