我正在努力应对超级简单的交易。它始终失败,并显示消息“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());
}
});
}
答案 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
是您要移动文档的位置。
流程如下:
Get
来自fromPath
位置的文档。- 醇>
Write
将文档转到toPath
位置。