-
Notifications
You must be signed in to change notification settings - Fork 987
Closed
Labels
Description
[REQUIRED] Describe your environment
- Firebase SDK version: 9.10.0
- Firebase Product: firestore
[REQUIRED] Describe the problem
transaction.get(ref) followed by transaction.set(ref, {...}) is causing the transaction to fail with error 'Document already exists' if the document was created by another app between the get and set.
Expected behavior is for the transaction to fail the first attempt because the document changed (was created) between the read and write. But it's also expected that the transaction will automatically retry.
I see the expected behavior in v9.6.11, and the error in v9.10.0. There appears to be a regression somewhere in between these versions.
Steps to reproduce:
- Before repro, execute
clean()to delete the document. - Execute method
transact(). - During the sleep in
transact(), execute methodwrite(). This might be done by a second browser. - Observe that the transaction from step 2 fails without retry. But the transaction retries and is successful in 9.6.11.
Relevant Code:
async function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function clean() {
console.log("starting clean")
await deleteDoc(ref);
console.log("finished clean")
}
async function write() {
await setDoc(ref, {created: (new Date()).toUTCString()})
console.log("Doc created")
}
async function transact() {
await runTransaction(db, async (tx) => {
const snapshot = await tx.get(ref);
console.log("doc read")
if (snapshot.exists()) {
console.log("document exists - updating last write")
tx.update(ref, {lastWrite: (new Date()).toUTCString()})
return;
}
console.log("sleeping")
await sleep(10000);
console.log("wake from sleep")
tx.set(ref, {created: (new Date()).toUTCString()});
});
console.log("Transaction successful");
}
async function reproduce()
{
await clean();
setTimeout(write, 2000);
transact();
}
reproduce();vinodgubbala and milo-