节点:检查 Firebase 数据库,并在对象时间与当前时间匹配时执行函数



Background

我有一个基于 Node 和 React 的应用程序。我正在使用 Firebase 作为我的存储和数据库。在我的应用程序中,用户可以填写一个表单,在其中上传图像并选择将图像添加到其网站的时间。我像这样将每个图像更新保存为Firebase数据库中的对象。图像按更新时间升序排列。

user-name: {
images: [
{
src: 'image-src-url',
updateTime: 1503953587727
}
{
src: 'image-src-url',
updateTime: 1503958424838
}
]
}

规模

我的应用程序数据库可能会变得非常大,有很多用户和图像。我想确保可扩展性。

问题

如何检查何时满足特定图像对象时间,然后执行函数?(我不需要有关正在运行的实际功能的帮助,只需在特定时间内检查数据库即可。

尝试

我考虑过使用 node-cron 做一个 cron 作业,它每 60 秒检查一次整个数据库(用户只能指定映像更新的分钟数,而不是秒数)。然后,如果它找到匹配的更新时间并执行我的函数。我担心的是,在大规模上,cron 作业将需要一段时间来搜索数据库并可能错过时间。

我还考虑过用户何时计划新的更新,然后为该时间动态创建特定的 cron 作业。我不确定如何做到这一点。

还有其他可能有效的方法吗?我对节点 cron 的担忧是否无效?

我能想到的有两种方法:

  1. 跟踪您上次处理的时间戳
  2. 将"要处理的事情"保留在队列中

跟踪您上次处理的时间戳

处理项目时,使用当前时间戳作为查询的截止点。像这样:

var now = Date.now();
var query = ref.orderByChild("updateTime").endAt(now)

现在,请确保将此now存储在某个位置(即数据库中),以便下次可以重复使用它来检索下一批项目:

var previous = ... previous value of now
var now = Date.now();
var query = ref.orderByChild("updateTime").startAt(previous).endAt(now);

这样,您一次只能处理一个切片。唯一棘手的一点是,有人可能会插入一个新节点,其中包含您已经处理过的updateTime。如果您的用例担心这一点,您可以使用updateTime上的验证规则来阻止他们这样做:

".validate": "newData.val() >= root.child('lastProcessed').val()"

当您向数据库添加更多项目时,您确实会查询更多项目。因此,这种方法存在可扩展性限制,但这种方法应该适用于多达数十万个节点的任何东西(我已经有一段时间没有测试了,所以 ymmv)。

对于之前关于列表大小的几个问题:

  • Firebase 性能:每个节点有多少个子节点?
  • Firebase 可扩展性限制
  • Firebase 中有多少条记录/行/节点很多?

将"要处理的事情"保留在队列中

另一种方法是保留仍需要处理的项目队列。因此,客户端将要处理的项目添加到队列中,并updateTime要处理的时间。您的服务器从队列中选取项目,执行必要的更新,然后从队列中删除该项目

var now = Date.now();
var query = ref.orderByChild("updateTime").endAt(now)
query.once("value").then(function(snapshot) {
snapshot.forEach(function(child) {
// TODO: process the child node
// remove the child node from the queue
child.ref.remove();
});
})

与早期方法的不同之处在于,队列的稳定状态将为空(或至少相当小),因此您的查询将针对更小的列表运行。这也是为什么您不需要跟踪上次处理的时间戳:到目前为止队列中的任何项目都有资格进行处理。

最新更新