TL; DR
每次我的Fiestore管理服务器重新启动时,即使我已经收听了文档并对其进行了处理,我的文档监听器也会被触发。我该如何解决这个问题?
结束TL; DR
我正在为我的Firestore聊天应用程序构建后端。基本思想是,只要用户通过客户端应用程序输入聊天消息,后端服务器就会侦听新消息并对其进行处理。
我遇到的问题是每当我重启我的应用服务器时,都会触发所有现有已处理聊天的监听器。因此,它会响应每个聊天,即使它之前已经响应过。我希望应用服务器只响应它尚未响应的新聊天。
我有一个想法,就是在每个聊天文档上放置一个布尔标志。当后端处理聊天文档时,它将设置标志。然后,监听器将仅回复没有设置标志的聊天。
这是一种合理的方法还是有更好的方法?我担心的一个问题是,每次重新启动我的应用服务器时,我都会收取大量费用来重新查询以前的所有聊天记录。我的另一个问题是听力似乎受到记忆限制?如果我的应用程序大规模扩展,我必须将所有聊天文档存储在内存中吗?这似乎不会很好地扩展......
//Example listener that processes chats based on whether or not the "hasBeenRepliedTo" flag is set
public void startFirestoreListener() {
CollectionReference docRef = db.collection("chats");
docRef.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@javax.annotation.Nullable QuerySnapshot queryDocumentSnapshots, @javax.annotation.Nullable FirestoreException e) {
if(e != null) {
logger.error("There was an error listening to changes in the firestore chats collection. E: "+e.getLocalizedMessage());
e.printStackTrace();
}
else if(queryDocumentSnapshots != null && !queryDocumentSnapshots.isEmpty()) {
for(ChatDocument chatDoc : queryDocumentSnapshots.toObjects(ChatDocument.class)) {
if(!chatDoc.getHasBeenRepliedTo() {
//Do some processing
chatDoc.setHasBeenRepliedTo(true); //Set replied to flag
}
else {
//No-op, we've already replied to this chat
}
}
}
}
});
}
答案 0 :(得分:2)
是的,为避免一直收到每个文档,您必须构建一个查询,只生成您知道已处理的文档。
不,您无需查询文件。您只需阅读它们,如果您的查询产生文档,就会发生这种情况。
是的,您必须能够在内存中保存查询的所有结果。
如果使用Cloud Functions接收集合中每个新文档的事件,则问题将更容易解决。您不必担心上述任何事情,而只是担心编写一个Firestore trigger来为每个新文档执行您想要的操作,并为这些调用付费。