0

In this question answer, @Frank van Puffelen explains how Realtime Database increment atomic operations ServerValue.increment(1) work:

    Client            Server                Client

               +                   +                   +
  increment(1) |                   |                   |
               |                   |                   | increment(1)
               |  (increment, 1)   |                   |
               +--------->---------+   (increment, 1)  |
               |                   |---------<---------+
               +---------<---------+                   |
               |      (ack, 2)     |--------->---------+
               |                   |     (ack, 3)      |
               |                   |                   |
               v                   v                   v

What if, after sending "(increment, 1)", the client somehow loses connection and does not receive "(ack, 2)"?

In my tests, it simply retries and sometimes it causes duplicated incrementation. It happens sometimes under poor connection situations. :(

Is it an expected behaviour?

To reproduce the tests, simply execute the sample below while you repeatedly turn on and off your internet connection (WiFi or 4G), to emulate a poor connection situation:

val updates: MutableMap<String, Any> = HashMap()
updates["posts/$key/starCount"] = ServerValue.increment(1)
updates["user-posts/$uid/$key/starCount"] = ServerValue.increment(1)
database.updateChildren(updates)
Geraldo Neto
  • 3,670
  • 1
  • 30
  • 33

1 Answers1

1

I wouldn't expect this to happen a lot, but it is possible. If you find this happens more than you consider acceptable, you have two options:

  1. Consider using a transaction instead of an atomic increment. Unlike atomic increments, transactions fail when there is no connection.
  2. Come up with security rules that allow the first increment and reject additional on, essentially making the increment idempotent.
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807