非常简单的Firestore事务失败

我正在努力进行超级简单的交易。 它总是失败并显示“Transaction failed all retries”消息,但除了logcat之外没有任何错误消息。

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

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

 private void copy( final DocumentReference SOURCEDOCREF, final CollectionReference TARGETCOLREF) { Transaction.Function transaction = new Transaction.Function() { @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 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() { @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()); } }); } 

根据有关交易的文件 :

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

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

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

事务可能由于以下原因而失败:

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

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

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

 public void cloneFirestoreDocument(DocumentReference fromPath, final DocumentReference toPath) { fromPath.get().addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { DocumentSnapshot document = task.getResult(); if (document != null) { toPath.set(document.getData()) .addOnSuccessListener(new OnSuccessListener() { @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. fromPath位置Get文档。
  2. 将文档写入toPath位置。