Java 非常简单的Firestore事务失败
我正在为一个超级简单的交易而挣扎。它总是失败,消息为事务失败所有重试,但除了logcat上的错误消息外,没有其他错误消息 当我调试它时,我看到它被重试了好几次。我真的不知道为什么,因为其他事务运行时没有问题 我只想将一个文档从一个集合克隆到另一个集合。从视频到收藏夹我知道这可以在交易之外完成,正如@Alex指出的,但这只是失败的一部分,真正的交易更长Java 非常简单的Firestore事务失败,java,android,firebase,google-cloud-firestore,Java,Android,Firebase,Google Cloud Firestore,我正在为一个超级简单的交易而挣扎。它总是失败,消息为事务失败所有重试,但除了logcat上的错误消息外,没有其他错误消息 当我调试它时,我看到它被重试了好几次。我真的不知道为什么,因为其他事务运行时没有问题 我只想将一个文档从一个集合克隆到另一个集合。从视频到收藏夹我知道这可以在交易之外完成,正如@Alex指出的,但这只是失败的一部分,真正的交易更长 private void copy( final DocumentReference SOURCEDOCREF, final C
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());
}
});
}
在这种情况下,不需要使用事务。要将文档从一个位置复制到另一个位置,请使用以下方法:
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是要移动文档的位置
流程如下:
从fromPath位置获取文档。
将文档写入toPath位置。
根据报告:
如果一个事务读取文档,而另一个客户端修改
对于这些文档,Cloud Firestore将重试事务。此功能
确保事务在最新且一致的数据上运行
因此,如果在事务完成之前对源文档进行了修改,则可以预期事务将重试
您还可以预期事务可能会失败
事务可能因以下原因而失败:
事务包含写入操作之后的读取操作。读取操作必须始终位于任何写入操作之前。
事务读取在事务外部修改的文档。在这种情况下,事务将自动再次运行。
事务重试次数有限。
失败的事务返回一个错误,不向其写入任何内容
数据库。您不需要回滚事务;云
Firestore会自动执行此操作
我会尽快试一试。然而,你能想出我前面的问题不起作用的原因吗?它的作用完全相同,只是在一个事务内部。此外,我认为可能需要一个事务不确定?因为一个用户可能会在文档编写时删除该文档,或者类似的情况。事实并非如此。您正在使用这行代码:setModeMODE\u FOLLOW;具有异步行为的addOnSuccessListener内部。这意味着,在您运行事务时,该行代码尚未调用。请查看以了解事务的用途。请尝试一下,并与我保持联系。谢谢,Doug。如你所见,我不会做那样的事。这就是为什么我很高兴这么简单的交易总是失败,而我有很多复杂的交易从来没有失败过。如果你认为这里有一个bug,请创建一个bug报告并提交一个bug报告。嗯,我不确定,只是想问问有经验的人他们是否看到我的问题code@DougStevenson是否有任何方法在特定重试后中止事务。如果我没有错,事务的最大重试次数是25次。因此,我想知道是否有任何方法可以在5次重试后停止事务。在我的例子中,当事务尝试失败时,不会调用OnFailureListener。