非常简单的Firestore事务失败

时间:2018-04-27 14:37:56

标签: java android firebase google-cloud-firestore

我正在努力应对超级简单的交易。它始终失败,并显示消息“Transaction failed all retries”,但logcat上除此之外没有任何错误消息。

当我调试它时,我发现它正在重试几次。我真的不知道为什么,因为其他交易没有问题。

我只想将一个文档中的一个文档克隆到另一个集合中。从“videos”到“favorites”思考(我知道这可以在事务之外完成,因为@Alex指出,但这只是失败的部分,真正的交易更长)

private void copy(
    final DocumentReference SOURCEDOCREF, 
    final CollectionReference TARGETCOLREF) {

        Transaction.Function<? extends Void> transaction = new Transaction.Function<Void>() {

            @Nullable
            @Override
            public Void apply(@NonNull Transaction transaction) throws FirebaseFirestoreException {

                DocumentSnapshot doc = transaction.get(SOURCEDOCREF);
                if (doc.exists()) {
                    DocumentReference favoriteRef = TARGETCOLREF.document("FV_" + doc.getId());
                    Map<String, Object> data = doc.getData();
                    transaction.set(favoriteRef, data);
                    return null;

                    // NOTE: This is reached, ie. the source doc exists
                    // the data recovered, and set into the transaction.
                } else
                    throw new FirebaseFirestoreException("Item does not exist", FirebaseFirestoreException.Code.NOT_FOUND);
            }
        };

        setMode(MODE_SPLASH);
        FirebaseFirestore.getInstance().runTransaction(transaction)
                .addOnSuccessListener(
                        (Activity) getContext(),
                        new OnSuccessListener<Object>() {
                            @Override
                            public void onSuccess(Object aVoid) {
                                setMode(MODE_FOLLOW);
                            }
                        })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        hide();
                        DialogHelper.customToast(getContext(), e.getMessage());
                    }
                });
    }

2 个答案:

答案 0 :(得分:2)

根据documentation about transactions

  

如果事务读取文档而另一个客户端修改任何文档   这些文档,Cloud Firestore重试该事务。此功能   确保事务以最新且一致的数据运行。

因此,如果在交易完成之前修改了源文档,您可以预期将重试您的交易。

您还可以预期交易可能会失败。

  

交易可能因以下原因而失败:

     
      
  • 事务包含写操作后的读操作。在任何写操作之前必须始终进行读操作。
  •   
  • 该事务读取在事务之外修改的文档。在这种情况下,事务会自动再次运行。   该交易重试次数有限。
  •   
     

失败的事务会返回错误并且不会写入任何内容   数据库。您不需要回滚事务;云   Firestore会自动执行此操作。

答案 1 :(得分:1)

在这种情况下无需使用交易。要将文档从某个位置复制到另一个位置,请使用以下方法:

public void cloneFirestoreDocument(DocumentReference fromPath, final DocumentReference toPath) {
    fromPath.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if (task.isSuccessful()) {
                DocumentSnapshot document = task.getResult();
                if (document != null) {
                    toPath.set(document.getData())
                        .addOnSuccessListener(new OnSuccessListener<Void>() {
                            @Override
                            public void onSuccess(Void aVoid) {
                                Log.d(TAG, "DocumentSnapshot successfully written!");
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Log.w(TAG, "Error writing document", e);
                            }
                        });
                } else {
                    Log.d(TAG, "No such document");
                }
            } else {
                Log.d(TAG, "get failed with ", task.getException());
            }
        }
    });
}

其中fromPath是您要移动的文档的位置,toPath是您要移动文档的位置。

流程如下:

  
      
  1. Get 来自 fromPath 位置的文档。
  2.   
  3. Write 将文档转到 toPath 位置。
  4.