Sunday, 1 September 2013

Firebase in Java/Android: The transaction was overridden by a subsequent set

Firebase in Java/Android: The transaction was overridden by a subsequent set

My multiplayer game using Firebase SDK for Java/Android has game rooms
where 4 players can play together.
In order to implement the matchmaking, I have a Firebase reference for
every room that players can join to. Each of these references has 4 slots
(as child nodes) containing the UUIDs of the players that are taking part
or an empty string if the slot is still available.
In order to prevent two (or more) players from claiming the same slot
simultanteously, I'm using transactions. Is the following code correct for
that purpose?
private int mUserSlot;
firebaseReference.runTransaction(new Transaction.Handler() {
@Override
public Result doTransaction(MutableData currentData) {
for (int s = 0; s <= 3; s++) { // loop through all slots
final String slotValue =
currentData.child(slotFromLocalID(s)).getValue(String.class);
if (slotValue == null || slotValue.equals("") ||
slotValue.equals(mUserUUID)) { // if slot is still available
currentData.child(slotFromLocalID(s)).setValue(mUserUUID);
mUserSlot = s;
return Transaction.success(currentData);
}
}
return Transaction.abort();
}
@Override
public void onComplete(FirebaseError error, boolean committed,
DataSnapshot currentData) {
if (error == null) {
if (committed) {
System.out.println("User is now in slot "+mUserSlot);
}
else {
System.out.println("User could not join, all slots
occupied");
}
}
else {
System.out.println("Error: "+error.getMessage());
}
}
});
However, I'm throwing an Exception in the error != null branch in
onComplete() above for debugging and after some test runs, I could see the
following error message (from error.getMessage() in my debug logs:
The transaction was overridden by a subsequent set
What does that mean, exactly? I thought the transactions are to prevent
concurrent access to the same fields which overwrite each other. Could
that mean that some other part of the application is writing to that field
without a transaction?
In this case, can I just handle it as I do with !committed? That means, in
both cases, the value that I wanted to write is not there after the
transaction has completed, is this correct?

No comments:

Post a Comment