1

I'm a pretty new Firebase user, and I noticed that currentData can be null the first time it is read by the app since it was launched. (Please trust that there is data where I do a transaction.)

But I don't see any way around this problem (other than calling the function that performs the transaction again, which I'd like to avoid), because if I add a condition to know if currentData is null, I have to return either Transaction.success(newCurrentData) or Transaction.abort() anyway. In both cases the transaction (doTransaction()) will not be re-run. I need to know the value at this location the first time, because depending on what is there, different actions will be performed.

So either modify the runTransaction() so that there is no more empty currentData (which seems - I think - impossible), or do something like myRef.keepSynced(true) to create the necessary cache before launching the transaction. Unfortunately I don't know these functions very well, and I don't know if they will work. That's why I'm calling on you.

Here is the relevant part of my transaction :

var roomName = ""
database.getReference("rooms").runTransaction(object : Transaction.Handler {
    override fun doTransaction(currentData: MutableData): Transaction.Result {
        roomName = currentData.children.toList().randomOrNull()?.key //enter to a random existing room
            ?: database.getReference("rooms").push().key!! // or create one if there is no room
        //Do some stuffs depending on roomName, and update the currentData
        return Transaction.success(currentData)
    }
    override fun onComplete(error: DatabaseError?, committed: Boolean, currentData: DataSnapshot?) {
    }
}

The currentData is empty the first time (in fact it is not null - since I code in Kotlin -, but does not change the question I ask). If I re-run the transaction without closing my app, there is now a child in the currentData.

TheBigBadBoy
  • 611
  • 5
  • 14

1 Answers1

1

On the first invocation of doTransaction the currentData will likely be empty. This is not related to the existence of data in the database, but on knowledge of that data in the client. It being empty is fully expected, and your code should handle it.

So if the existing data would not exist, what should the transaction do? Even just leaving it empty is fine, as long as you do something valid it will auto-correct on the next try (or one of the ones after that).

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • In fact, if there is data (ie a random key "room"), I want to write in it. But if there is none, I have to create another random key "room". So the problem is every first time, the client will create a "room" that was not intended. Is it possible to know the difference between (1) currentData is empty and (2) the cache of currentData wasn't already created (first exe) ? – TheBigBadBoy Feb 11 '21 at 09:12
  • Since the client seems to have no knowledge of the state, there is no way to distinguish between cases 1 and 2. – Frank van Puffelen Feb 11 '21 at 14:36
  • So I see only one solution (feel free to tell me if you see another one): by always leaving any data (useful or not) at this reference I could easily know if currentData is empty when it should "not" be (I understood that this case was intentional, even if it "annoys" me a bit). Is this recommended, or on the contrary would it be better not to do this kind of thing? – TheBigBadBoy Feb 12 '21 at 17:25
  • 1
    I don't fully understand the problem, so it's hard to say. But if you add a room to the "empty" `MutableData` on the first try, and that transaction is retried because data already exists under `rooms`, the room you initially added to the `MutableData` is never created in the database. Instead your handler will be called again with the new guess as to the data in `rooms`, and you can set the correct new state. – Frank van Puffelen Feb 12 '21 at 17:48