Home > database >  How can i avoid the duplicate Field counter from two user at the same time pressing the bottom
How can i avoid the duplicate Field counter from two user at the same time pressing the bottom

Time:01-20

i have collection which contains the whole users products , and to avoid the casts of reading all docs to get the length of the collection , i increase one value 1 to every field once it's doc being created , ok now everything is ok

here i am using this method to chick if doc if exist or not so i can avoid the duplicate of counter in case offline mode

 removeProduct1(){
    FirebaseFirestore.instance.collection("product").doc('product1')
        .get(const GetOptions(source: Source.server)).then((value1) {
      if(value1.exists) {
        FirebaseFirestore.instance.collection("product").doc('product1').delete();
        FirebaseFirestore.instance.collection("product").doc('productCount').update({
          'productCount': FieldValue.increment(-1),
        });
      }
    }).onError((error, stackTrace) {
      ScaffoldMessenger.of(context).showSnackBar(snackBar,);
      });
  }

also everything is ok , but i noticed if two user pressed the button for this method at the same time so its gonna be two value decrease -2 maybe someone will think its rarely when two user hit the button at the same time , well this is only simple sample of what i have for real instead , i have page which contains too many users which is not be rarely for being two user hit the button

EDIT FOR MOER EXPLATION

i have collection called Friends which contains User IDs of friends together for example user1 his id is ABC and user2 his id is DEF so id becomes final into the Friends collection like this ABCDEF by following function and also this following function increase counter 1 for ever one of them

makeFriends(){
  // here i make sure first if the friends Ids are not exists To avoid suspiciously increasing the counter in offline mode and its work very well 
  

    FirebaseFirestore.instance.collection("Friends").doc(user1Id user2Id).get().then((value) {
        if(!value.exists){
          // here to add ids to the friends collection 
          FirebaseFirestore.instance.collection("Friends").doc(user1Id user2Id).set({
            'test':''
          });
          //here to increase counter in other colection which is users for both user 
          //user1
      FirebaseFirestore.instance.collection("users").doc(user1Id).update({
        'friendsCounter':FieldValue.increment(1)
      });
      //user2
      FirebaseFirestore.instance.collection("users").doc(user2Id).update({
        'friendsCounter':FieldValue.increment(1)
      });
    }
  });
}
 

Okay now everything going fine and they became a friends with one value increased and their Ids became unit into Friends collection .. and here image for better explanation

image 1

image

here i have function responsible for deleting friend with decrease one value from FriendsCount Field for both of them

deleteFriends(){
  // here i make sure first if the friends Ids are exists To 
  // avoid suspiciously decrease the counter in offline mode and its work very well
  FirebaseFirestore.instance.collection("Friends").doc(user1Id user2Id).get().then((value) {
    if(value.exists){
      // here to remove ids from the friends collection
      FirebaseFirestore.instance.collection("Friends").doc(user1Id user2Id).delete();
      //here to decrease counter for both user
      //user1
      FirebaseFirestore.instance.collection("users").doc(user1Id).update({
        'friendsCounter':FieldValue.increment(-1)
      });
      //user2
      FirebaseFirestore.instance.collection("users").doc(user2Id).update({
        'friendsCounter':FieldValue.increment(-1)
      });
    }
  });
}

ok now also everything going fine .. lets say user1 deleted his friend user 2 , by the previous functionthe Friends id which is ABCDEFhas been deleted so next time if user 2 want to do the same opretion it will fail because Friends ids are not exist anymore ..

the problem IS : lets say these two users are still friends and these two user visited each others profiles and hit the button at the same time which is call the pervious function (deleteFriend) so they gonna get the same return value which is (yes exists) then will be double decrease value for both of them instead of one as required .

means if their friendsCount was 1 both of them when they was a friend so tee value will be -1 instead 0 because there two operation was proceed

and this happen only if these two user hit the button at the same moment , but if the user 1 hit the button before user 2 then user 2 want to do same operation so he ganna fail because friendId was deleted by user1 operation as a condition statement in previous function ..

if(value.exists) i thought it too fast to delete friendIds before it give same result to other user if they together call the function at the same time   

of course i can prevent the button of calling the delete function in case one of these user is already deleted other but I didn't see this as a strong solution since i can't grantee traffic jam or any reason else like bad users behavior .. etc , also basically i can't do it because delete button must be available as long as they still a friends

Note: this also happen in addFriends buttom call too if two users hit it at the same time , double value 2 instead one ..

i need any way to avoid server to give same result if there was two user query same doc at the same time , or any good solution

CodePudding user response:

If you need to both read and write a document to update it, you should use a transaction to prevent the race condition that you now have when multiple users perform the operation around the same time.

Here you definitely want to use a transaction, because if the delete fails for whatever reason, the decrement operation should also fail (and vice versa).

The FlutterFire documentation on transactions also has a good explanation and example code to get started.

  •  Tags:  
  • Related