1

I've got the problem when two people at the same time tries to add each other to friends. So, at first when one person presses add to friends he checks, whether other user's groups doesn't have my ID. If he has, I don't need to create new group - I will just add this group's ID to my list, else - I will create new group. Now, when two people at the same time press that button, they both get the result that group doesn't exist thus they both create a new group. How to solve these kind of problems?

Structure:

 "userGroups" : {
     "myId1" : {
         "generatedGroupId1" : "myFriendID1"
      }
  }

Update: I've managed to do it: basically in doTransaction I create group if it doesn't exist and then on onComplete I work with already created group. If two people start creating new group, one end up creating it, second one - reading it.

        // function
        ref.runTransaction(object : Transaction.Handler {
            override fun doTransaction(currentData: MutableData): Transaction.Result {
                // create group here if data is null
                return Transaction.success(currentData)
            }

            override fun onComplete(
                error: DatabaseError?,
                committed: Boolean,
                currentData: DataSnapshot?
            ) {
                Log.d(TAG, "postTransaction:onComplete:" + error)
                // continue doing stuff, group already exists at this point
            }
        })
}
Captain Jacky
  • 888
  • 1
  • 12
  • 26

1 Answers1

1

It's hard to give specific without seeing your code, but the most likely options are (in order of my personal preference):

  1. Base the group ID on the two users in it. If you do this correct, the two users will end up with the same group ID, and it doesn't matter who is first. Creating the groups then becomes a so-called idempotent operation, which means that if you run the same operation multiple times, it will have the same result. For an example of such group IDs, see Best way to manage Chat channels in Firebase
  2. Use a transaction to ensure only one write makes it through. This would mean that the second user ends up reading the group created by the first user, and can then cancel their data creation.
  3. Use a Cloud Function, which can perform more (non-atomic) read operations to check whether the group of users already exists, and reject the request from the second user.
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • I've updated my code (in the post) as I'm using a transaction. Now both of users create new group, but for one user transaction runs again and then acts as group already exists. Do I need to return those updates somewhere or how to prevent this? – Captain Jacky Mar 12 '21 at 07:00
  • I'm not sure I understand what you're saying there. It might be best to open a new question, with a clear reproduction of the problem you have with a transaction. – Frank van Puffelen Mar 12 '21 at 15:29