Flutter应用在Cloud Firestore上执行的并发交易时崩溃

时间:2019-11-26 13:08:31

标签: firebase flutter google-cloud-firestore

我正在尝试开发一个可让多个用户登录并同时完成民意测验的应用程序。

在这种情况下,用户提交答案后,便立即进行交易以增加给定答案的计数器

      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);
    });

多个用户同时提交同一问题的相同答案,即多个用户同时请求更新同一文档中的同一字段,应用崩溃并产生以下错误:

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

不知道为什么会这样,因为事务处理应该允许多个用户同时更新文档的字段。

2 个答案:

答案 0 :(得分:1)

如果您在物理iOS设备上运行,则崩溃由此bug in the FlutterFire binding library引起。似乎没有解决方法,因此请密切注意更新问题。

答案 1 :(得分:0)

我通过使事务对象(tx)变为非异步并将异步逻辑移到事务块之外来解决此问题。毕竟,事务的全部目的是原子地执行其指令,而异步指令则有损于此目的。