Reputation: 151
Some questions regarding Transaction in Firebase.
Transaction documentation says read before write. Let's say if I t.get()
2 documents in a db.runTransaction(t)
in the beginning. Then mid-way in the runTransaction code block, I t.update()
both documents. Does it mean that if there are any changes in the 2 documents beyond the t.update()
, the runTransaction will retry?
Also, if I do a normal document get()
within the transaction code block, will changes in the document after the get()
within the transaction cause the transaction to retry?
db.runTransaction(async t => {
const snapshot1 = await t.get(db.collection('col1').doc('doc1'));
const snapshot2 = await t.get(db.collection('col2').doc('doc2'));
const snapshot3 = await db.collection('col3').doc('doc3').get();
// changes in col1.doc1 or col2.doc2 will trigger retry
// QUESTION: Will changes in col3.doc3 trigger a retry?
doSomething(snapshot1);
doSomething(snapshot2);
await Promise.all([
t.update(snapshot1.ref, { field1: 'a' }),
t.update(snapshot2.ref, { field1: 'b' })
]);
// QUESTION: will changes in col1.doc1 or col2.doc2 externally beyond here trigger a retry
doSomething(snapshot3);
});
Appreciate all your expert views/insights. Thanks.
Upvotes: 1
Views: 438
Reputation: 83191
Does it mean that if there are any changes in the 2 documents beyond (before) the
t.update()
, the Transaction will retry?
Yes, as explained in the doc: "In the case of a concurrent edit, Cloud Firestore runs the entire transaction again"
Also, if I do a normal document get() within the transaction code block, will changes in the document after the get() within the transaction cause the transaction to retry?
You should not fetch a document with a "normal" get()
but use the transaction's get()
method (i.e. t.get()
). With a normal get()
the document will not be "included" in the transaction.
In addition, note that you don't need to do:
await Promise.all([
t.update(snapshot1.ref, { field1: 'a' }),
t.update(snapshot2.ref, { field1: 'b' })
]);
because t.update()
is not asynchronous. It does not return a Promise but the Transaction instance itself, and can be used for chaining method calls like:
t.update(snapshot1.ref, { field1: 'a' }).update(snapshot2.ref, { field1: 'b' })
Note that it's similar for set()
and delete()
.
Upvotes: 2