Reputation: 61
I'm using firebase realtime database for android, doing transaction to update an object, what suppose to block 2 users from overriding one each other. that seems to work.
The problem: one user blocked from writing so doTransation()
will be called again as should.
According to my logic below first doTransation call won't take affect on the server. second doTransation call will do abort.
after the first doTransation and before the second, I getting the callback onDataChange()
to my ValueEventListener with the data that was rejected/ not committed and before onComplete()
called.
any idea why this behavior? how do I change it?
fun onIconClicked(currentGameState: GameState, gameId: String, iconClicked: Long) {
Log.d(TAG, "onIconClicked() called")
database.child(GAME_STATE_PATH).child(gameId).runTransaction(object : Transaction.Handler {
override fun doTransaction(currentData: MutableData): Transaction.Result {
val gameState = currentData.getValue(GameState::class.java)
?: return Transaction.success(currentData)
// make sure the state from server match the client, and check if won the card
return if (gameState == currentGameState && true == currentGameState.users?.get(currentUserId)?.card?.contains(iconClicked) &&
true == currentGameState.mainCard?.contains(iconClicked)) {
// player won card - make the changes in game state...
currentData.value = gameState
Log.d(TAG, "doTransaction() winning card, game after = $gameState")
Transaction.success(currentData)
} else {
Log.d(TAG, "doTransaction() aborting")
Transaction.abort()
}
}
override fun onComplete(error: DatabaseError?, committed: Boolean, currentData: DataSnapshot?) {
Log.d(TAG, "onIconClicked onComplete() called with: error = $error, committed = $committed, currentData = $currentData")
}
})
}
Upvotes: 0
Views: 294
Reputation: 599766
I getting the callback
onDataChange()
to myValueEventListener
with the data that was rejected/ not committed and beforeonComplete()
called.
Listeners on the same client where the transaction runs will indeed see local events for intermediate transaction iterations.
If you don't want these local events to fire, use the overload of runTransaction
that takes a second argument called fireLocalEvents
, and pass false
for that.
So:
database.child(GAME_STATE_PATH).child(gameId).runTransaction(..., false)
Upvotes: 1