Reputation: 351
I use Firebase transactions to get compare value and then update the value of a document in a collection.
but when I use the same data and send the query at the same time, they both read the same value so the check I do pass for both, and I have a bad result a the end. the field is decremented twice.
my transaction is:
let docRef = db.collection('X').doc('SF');
let reduceValue = 20;
let transaction = db.runTransaction(t => {
return t.get(docRef)
.then(doc => {
let value = doc.data().y ;
if (value >= reduceValue) {
t.update(cptRef, { y:FieldValue.increment(-reduceValue) });
return Promise.resolve('Y increased');
} else {
return Promise.reject('sorry y is ');
}
});
}).then(result => {
console.log('Transaction success', result);
}).catch(err => {
console.log('Transaction failure:', err);
});
Thanks.
Upvotes: 0
Views: 1234
Reputation: 83058
If I understand correctly your question, what you are describing is the correct behaviour of a Firestore Transaction executed with one of the Firestore Client SDKs:
The fact that your two calls are executed "at the same time" should not change the result: The counter should be decremented twice.
This is exactly what the Transaction ensures: In the case of a concurrent edit, Cloud Firestore runs the entire transaction again, ensuring that the initial doc (db.collection('X').doc('SF')
in your case) has not changed during the Transaction. If it is the case, it will retry the operation with the new data.
This is because the Client SDKs use optimistic concurrency for Transactions and that, consequently, there is no locking of the documents.
I suggest you watch the following official video which explains that in detail.
You will also see in this video that for Transactions executed from a back-end (e.g. using the Admin SDK) the mechanism is not the same: they implement pessimistic concurrency (locking documents during transactions).
Upvotes: 1