Database - Transactions
Transactions
When working with data that could be corrupted by concurrent modifications, such as incremental counters, you can use a transaction operation.
You give this operation an important argument: an instance of a TransactionHandler
.
This class will implement a function that takes the current state of the data as an argument and returns the new desired state you would like to write. If another client writes to the location before your new value is successfully written, your update function is called again with the new current value, and the write is retried.
Using a transaction prevents data from being incorrect if multiple users change the same data at the same time or the client had stale data. If the transaction is rejected, the server returns the current value to the client, which runs the transaction again with the updated value. This repeats until the transaction is accepted or too many attempts have been made.
In the following example we will start a transaction, by calling runTransaction()
on a DatabaseReference
and pass in an instance of a class that implements the
TransactionHandler
interface.
We will attempt to increment a "count" value which will be a synchronised counter.
var ref:DatabaseReference = FirebaseDatabase.service.getReference( "count" );
ref.runTransaction( new CountTransactionHandler() );
The implementation of the CountTransactionHandler
sets the logic for updating
the value of the data. It has one function doTransaction
that will be called
each time the Firebase transaction requires updating of the data value.
Here we will increment the count value:
public class CountTransactionHandler implements TransactionHandler
{
public function doTransaction( mutableData:MutableData ):TransactionResult
{
var data:Object = mutableData.getValue();
if (data == null)
{
// Set an initial value
mutableData.setValue( 0 );
return TransactionResult.success(mutableData);
}
mutableData.setValue( mutableData.getValue() + 1 );
return TransactionResult.success(mutableData);
}
}
You can use any logic in this doTransaction
function that you require. However it
is important that you return a TransactionResult
:
- on success use:
TransactionResult.success( mutableData );
- on failure use:
TransactionResult.abort();
Note: Because
doTransaction()
is called multiple times, it must be able to handlenull
data. Even if there is existing data in your remote database, it may not be locally cached when the transaction function is run, resulting innull
for the initial value.