Things to know about Transactions
- Read operations must come before write operations.
- A function calling a transaction (transaction function) might run more than once if a concurrent edit affects a document that the transaction reads.
- Transaction functions should not directly modify application state.
- Transactions will fail when the client is offline.
Transactions
I want to perform update on two documents, and I wanted to ensure both updates are successful, else it should be rolled back.
- Transaction require connection to the server in order to work, else it will raise exception of
FirebaseFirestoreException: Transaction failed all retries
when offline.
viewModel.firestore.runTransaction { transaction -> val oldRef = firestore.collection("test").document("TEST01") transaction.update(oldRef, mapOf( "hello" to "world" )) val newRef = firestore.collection("test").document("TEST02") transaction.update(newRef, mapOf( "hello" to "world" )) // return null - optional null}.addOnCompleteListener { if (it.isSuccessful) { Timber.d("Transaction success!") } else { // com.google.firebase.firestore.FirebaseFirestoreException: Transaction failed all retries. Timber.e(it.exception, "Transaction fail") }}
Batch Writes
Batch writes work in both online and offline mode, and updates would not be applied if one of the update fail.
- During offline mode,
addOnCompleteListener
will only fired when it goes online and apply the updates
val batch = firestore.batch()val oldRef = firestore.collection("test").document("EXISTING_ID")batch.update(oldRef, mapOf( "hello" to "world"))// this will fail as it tries to update on a new idval newRef = firestore.collection("test").document("NEW_ID")batch.update(newRef, mapOf( "hello" to "world"))batch.commit().addOnCompleteListener { if (it.isSuccessful) { Timber.d("Batch success") } else { // com.google.firebase.firestore.FirebaseFirestoreException Timber.e(it.exception, "Batch error") }}
References: