Flutter app crashes on concurrent transactions performed on cloud Firestore

北慕城南 提交于 2021-02-18 17:49:31

问题


I am trying to develop an app where multiple users log in and completes a poll concurrently.

In this, as soon as user submits the answer the transaction is ran to increment the counter for given answer

      try {
        DocumentSnapshot freshsnap = await tx.get(reff);
        try {
          await tx.update(reff, <String, dynamic>{
            '$i': freshsnap['$i'] + 1,
          });
        } catch (error) {
          print("Error" + error.code);
        }
      } catch (error) {
        if (error is PlatformException &&
            error.code == 'Error performing transaction') {
          // await tx.set(ref, data);
          print("Error" + error.code);
        } else
          rethrow;
      }
    }).catchError((onError){
      print("Error on: "+onError);
    });

as soon as the multiple users submit the same answer for same question concurrently i.e The same field in same document is requested to update by multiple users concurrently the app crashes and generates following error:

FATAL EXCEPTION: AsyncTask #1
E/AndroidRuntime(12169): Process: com.rrcg.tumerboared, PID: 12169
E/AndroidRuntime(12169): java.lang.RuntimeException: An error occurred while executing doInBackground()
E/AndroidRuntime(12169):        at android.os.AsyncTask$3.done(AsyncTask.java:354)
E/AndroidRuntime(12169):        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
E/AndroidRuntime(12169):        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
E/AndroidRuntime(12169):        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
E/AndroidRuntime(12169):        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E/AndroidRuntime(12169):        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/AndroidRuntime(12169):        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/AndroidRuntime(12169):        at java.lang.Thread.run(Thread.java:764)
E/AndroidRuntime(12169): Caused by: java.lang.AssertionError: INTERNAL ASSERTION FAILED: A transaction object cannot be used after its update callback has been invoked.
E/AndroidRuntime(12169):        at com.google.firebase.firestore.util.Assert.fail(com.google.firebase:firebase-firestore@@21.2.1:46)
E/AndroidRuntime(12169):        at com.google.firebase.firestore.util.Assert.hardAssert(com.google.firebase:firebase-firestore@@21.2.1:31)
E/AndroidRuntime(12169):        at com.google.firebase.firestore.core.Transaction.ensureCommitNotCalled(com.google.firebase:firebase-firestore@@21.2.1:246)
E/AndroidRuntime(12169):        at com.google.firebase.firestore.core.Transaction.lookup(com.google.firebase:firebase-firestore@@21.2.1:81)
E/AndroidRuntime(12169):        at com.google.firebase.firestore.Transaction.getAsync(com.google.firebase:firebase-firestore@@21.2.1:191)
E/AndroidRuntime(12169):        at com.google.firebase.firestore.Transaction.get(com.google.firebase:firebase-firestore@@21.2.1:228)
E/AndroidRuntime(12169):        at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$5.doInBackground(CloudFirestorePlugin.java:550)
E/AndroidRuntime(12169):        at io.flutter.plugins.firebase.cloudfirestore.CloudFirestorePlugin$5.doInBackground(CloudFirestorePlugin.java:545)
E/AndroidRuntime(12169):        at android.os.AsyncTask$2.call(AsyncTask.java:333)
E/AndroidRuntime(12169):        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/AndroidRuntime(12169):        ... 4 more

Have no idea why is this happening, since transaction should allow multiple users to update a field of a document concurrently.


回答1:


If you are running on a physical iOS device, the crash is caused by this bug in the FlutterFire binding library. There doesn't seem to be a workaround, so keep an eye on the issue for updates.




回答2:


I solved this by making the transaction object (tx) non-async and moving the async logic outside the transaction block. After all, the whole point of transactions is to execute its instructions atomically and async instructions kind of defeat this purpose.



来源:https://stackoverflow.com/questions/59051694/flutter-app-crashes-on-concurrent-transactions-performed-on-cloud-firestore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!