0

I'm attempting to do a Firebase Transaction, in order to change values in two locations in my Firebase Database, but the MutableData the transaction hands me is null.

Is it forbidden to run a Transaction on the Database root? Do I have to run multiple chained transactions in order to accomplish this?

val ref = FirebaseDatabase
    .getInstance()
    .getReference("/")

ref.runTransaction(object : Transaction.Handler {

  override fun doTransaction(currentData: MutableData): Transaction.Result {

    println( currentData) // { key = <none>, value = null }

    if (currentData.value == null){
        return Transaction.success(currentData)
    }

    currentData.child("users/{userID}/someVal/").setValue(X)
    currentData.child("items/{itemID}/someVal/").setValue(Y)
    return Transaction.success(currentData)
  }
})
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Jake
  • 115
  • 1
  • 3
  • 15
  • 1
    This is the expected behavior. Your transaction handler will (almost) always first be invoked with `null`, since the client doesn't *know* the value of the location yet. Using `null` as an initial guess, makes it possible that the transaction succeeds with a single request. See Kato's answer: http://stackoverflow.com/questions/28811037/data-in-transaction-is-null or mine here: http://stackoverflow.com/questions/33578887/transcation-updatefunction-parameter-is-null/33578953#33578953 – Frank van Puffelen Mar 22 '17 at 03:58
  • @FrankvanPuffelen Very well. I now set the data if the value is null and return Transaction.success(currentData). But the doTransaction method is never called again, and the values are never set on Firebase. [gist](https://gist.github.com/jacobattwobulls/136de48822da5caa0f0113d094425a77) – Jake Mar 22 '17 at 04:31
  • I'm not sure what's going on there. But in general I'd recommend against running transactions high in your JSON tree, since they're going to hurt scalability *a lot*. Instead of using a transaction, use a multi-location update from a trusted process (such as a server you control or a [Cloud Function](https://firebase.google.com/docs/functions/use-cases#perform_database_sanitization_and_maintenance)). – Frank van Puffelen Mar 22 '17 at 14:32

1 Answers1

1

You ask: Is it forbidden to run a Transaction on the Database root? I don't find it documented anywhere, but the answer seems to be Yes.

When I run code equivalent to yours (Java instead of Kotlin) with debug log statements added, the doTransaction() method is invoked repeatedly and onComplete() reports an error of The transaction had too many retries.

When I change the transaction location to some child of root, the transaction completes successfully.

Bob Snyder
  • 37,759
  • 6
  • 111
  • 158