skip to Main Content

I am importing a product catalog using Firebase DB with Flutter. Only 1 person can add the product to the cart. If 2 or more people want to add the product to the basket at the same time, the product is added to all of them. What can I do to get this back?

  void addBasket(Map<String, dynamic> data, index) async {

    var _storage = await GetStorage();

    final CollectionReference user_basket =
        await FirebaseFirestore.instance.collection('user basket');
    final CollectionReference product =
        await FirebaseFirestore.instance.collection('product');
    final DocumentReference ref = await product.doc(data['id']);
    await FirebaseFirestore.instance.runTransaction((Transaction tx) async {
      DocumentSnapshot snap = await tx.get(ref);
      if (snap.exists) {
       await product.doc(data['id']).delete();
        await tx.update(ref, data);


      await  user_basket
            .doc(_storage.read('uid'))
            .collection('basket')
            .doc(data['id'])
            .set(data);
        inArea.removeAt(index);
        Get.back();
        Get.back();
      } else {
      await  user_basket
            .doc(_storage.read('uid'))
            .collection('basket')
            .doc(data['id'])
            .delete();
        Get.back();
        Get.defaultDialog(
            title: "Wrong",
            middleText:
                "This product is being reviewed by another person.");
      }
    });
  }

I tried to use Transaction as you can see in the code. I tested this code the first time I wrote it. when two people pressed the button at the same time, one of the 2 could add the product to the cart. I wanted to test again today. I pressed the add product to cart button, as a result both the If and Else blogs worked. So I started getting errors. The exact result I want to get is when more than 1 person wants to add the same product to the cart, to get the opposite. Let the first click on the button add the product to the basket, and the others will be informed through the Alerd Dialog.

2

Answers


  1. I believe you are creating a race condition between clients. In all of my implementations of Firestore, I do not use await on the collection or query references. You should only need to await the get() method itself.

    When you look at Flutter Firestore documentation for their implementation of transactions, you’ll see they do not await the collection reference at the top.

    https://firebase.google.com/docs/firestore/manage-data/transactions#dart

    Instead of:

    final CollectionReference user_basket =
        await FirebaseFirestore.instance.collection('user basket');
    final CollectionReference product =
        await FirebaseFirestore.instance.collection('product');
    final DocumentReference ref = await product.doc(data['id']);

    Try using:

    final CollectionReference user_basket = FirebaseFirestore.instance.collection('user basket');
    final CollectionReference product = FirebaseFirestore.instance.collection('product');
    final DocumentReference ref = product.doc(data['id']);

    I hope that helps! I will try and put together a Firestore transactions demo to see if I can replicate and resolve that issue you described.

    Login or Signup to reply.
  2. It could be data race issue. you can use transaction class to prevent it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search