有时我的云函数会从 Firestore 返回旧数据。是缓存问题吗?

Posted

技术标签:

【中文标题】有时我的云函数会从 Firestore 返回旧数据。是缓存问题吗?【英文标题】:Sometimes my Cloud Function returns old data from Firestore. Is it a cache problem? 【发布时间】:2021-11-27 13:42:53 【问题描述】:

在客户端,我正在使用侦听器来检测用户的“通知”集合是否发生了变化。应用调用云函数,获取最后三个未读通知和未读通知总数。

在我的应用程序中,我有这个:

听众

      firestore.collection("users")
                .doc(uid)
                .collection("notifications")
                .snapshots().listen((QuerySnapshot querySnapshot) 
                     NotificationsPreviewModel notificationsPreview =
                  await _cloudFunctionsService.getNotificationsPreview(doctor.id)
        )

云功能

    exports.getNotificationsPreview = functions.https.onCall(async (data, context) => 
        const userId = data.userId;
        let notifications = [];
    
        const notificationsDocuments = await db
            .collection("users")
            .doc(userId)
            .collection("notifications")
            .orderBy("dateTime", "desc")
            .get();
    
        notifications = notificationsDocuments.docs.map((rawNotification) =>
            rawNotification.data()).filter((element) => element.unread == true);
    
        const notificationsNumber = notifications.length;
        notifications = notifications.slice(0, 3);
    
        return  "notifications": notifications, "notificationsNumber": notificationsNumber ;
    );

只有在检测到更改时才会调用 Cloud Function,因此它不应返回旧数据。

该错误仅在应用程序启动时第一次调用 Cloud Function 时出现,但并非总是如此。以下调用不会产生错误。

我该如何解决这个问题?目前,我添加了 500 毫秒的延迟,效果很好,但不是真正的解决方案。

【问题讨论】:

【参考方案1】:

至于documentation:

当您设置监听器时,Cloud Firestore 会向您的监听器发送数据的初始快照,然后在每次文档更改时发送另一个快照。

您似乎最初收到了数据的快照,然后按预期收到了以下更新。

您可以在this post 中查看一些可能的解决方案。

【讨论】:

如果我收到初始快照,则触发函数并调用 Cf,但这不是我的问题。问题是,在第一次更改时,CF 返回旧数据,所以它不是第一个快照,而是我的集合发生更改时的第一个快照【参考方案2】:

根据您的描述,您在从 Firestore 收集数据时似乎看到了某种形式的延迟。从云端检索数据需要时间,500ms 的延迟并不过分。

我对 Flutter 不够熟悉,无法评论您的代码。不过根据documentation for Java:

默认情况下,get() 会通过等待来自服务器的数据尽可能尝试提供最新数据,但如果您处于离线状态且无法访问服务器,它可能会返回缓存数据或失败。可以通过 Source 参数更改此行为。

Source:

通过提供 Source 值,可以将这些方法配置为仅从服务器获取结果,仅从本地缓存中获取结果,或者尝试从服务器获取结果并回退到缓存中(这是默认设置)。

如果您在线,get() 会检查服务器以获取最新数据,这可能需要 300 毫秒到 1500 毫秒,具体取决于多种因素。例如,与您的 Cloud Function 和客户端相比,您的 Firestore 实例位于何处?尝试调整延迟,看看是否能确定时间。

您还应该注意一些软限制,因为这也可能会影响您检索数据的速度。文档的最大持续写入速率为每秒 1 个。将写入速率维持在每秒一次以上会增加延迟并导致争用错误。

【讨论】:

Node.js SDK 不支持源选项,因为它没有离线支持(它始终在线)。我会做一个workaraound。

以上是关于有时我的云函数会从 Firestore 返回旧数据。是缓存问题吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用云函数将数据写入云 Firestore

当旧线程死亡时重新启动函数

导出 Firestore 备份数据的云功能。使用 firebase-admin 或 @google-cloud/firestore?

FireStore 不返回所有结果

无法通过Cloud Functions(onCall)从Cloud Firestore返回一个json数组到Swift

作为 Kotlin 中的函数的结果,如何从 Firestore 数据库返回列表?