は、次の点を考慮してバグ:これらは同じノードjsのプロセスから呼び出されFirebase取引
function useCredits(userId, amount){
var userRef = firebase.database().ref().child('users').child(userId);
userRef.transaction(function(user) {
if (!user){
return user;
}
user.credits -= amount;
return user;
}, NOOP, false);
}
function notifyUser(userId, message){
var notificationId = Math.random();
var userNotificationRef = firebase.database().ref().child('users').child(userId).child('notifications').child(notificationId);
userNotificationRef.transaction(function(notification) {
return message;
}, NOOP, false);
}
。
ユーザーは次のようになります。
{
"name": 'Alex',
"age": 22,
"credits": 100,
"notifications": {
"1": "notification 1",
"2": "notification 2"
}
}
私は私のストレステストを実行すると、私はuserRefトランザクション更新関数に渡さ時々ユーザーオブジェクトはそれだけで、次のされて完全なユーザーではないことに注意してください:
{
"notifications": {
"1": "notification 1",
"2": "notification 2"
}
}
これは明らかにuser.creditsが存在しないためにエラーが発生します。
userRefトランザクションの更新機能に渡されたユーザーオブジェクトが、userNotificationRefトランザクションの更新機能によって返されたデータと同じであることが疑わしいです。
これはなぜですか?この問題は、ユーザーの親の場所で両方のトランザクションを実行すると消えますが、効率的にロックしてユーザーオブジェクト全体を読み取るので、これはあまり最適ではありません。
トランザクションにこのような問題があったことはわかりませんでした... +1。トランザクションを必要とせずにこの "値を増やす"操作をどのように再設計することを提案しますか? – qxz
詳細な対応をいただき、ありがとうございます。トランザクションは多少壊れているようです - 私の意見では、クライアントはこれらのすべての考慮事項について心配する必要はありません。あなたは、銀行口座の残高がファイアーベースでの取引を使わずにモデル化されていることをどのように示唆しますか?トランザクションを使用してこれを処理する堅牢な方法がない場合は、これは深刻な制限だと感じています。別の問題は、ある値をトランザクション的に更新し、同時に他の場所を原子的に更新できることです。 – user3391835
これはすべて難しい経験であり、* hard *を重視しています。上記の注意点を念頭に置いている限り、トランザクションは単純に増分しても問題ありません。もう1つの方法は、ログに "+ N"エントリを押し込んで、サーバが定期的にトランザクションをロールアップさせる方法です。クライアントは、最後に集計された値とログを読み取り、その場で現在の値を計算することができます。ディープ・アトミック・アップデートは可能ですが、トランザクショナルにすることはできません。ログベースのデザインは、あなたの友人です。 – Piotr