我有一个基于节点的后端,它与mongoDb实例集成。DB有一组日历事件,每个事件都有一个唯一的日期-时间字段。我正在考虑在设定时间前15分钟执行提醒功能的最佳方式。
我想到的唯一想法是使用setInterval一致地查询DB,然后运行函数。有更好的方法吗?
显然,setInterval
和拉取数据库似乎是最简单的方法。下面的解决方案可以被视为数据库启动这些计划事件的替代方案,因此您将获得push而不是pull方法。
假设您有一个简单的集合scheduledEvents,其中包含一个类型为ISODate的字段scheduledAt。例如:
{ "_id" : ObjectId("5c457cb554651d56ffe0c759"), "scheduledAt" : ISODate("2019-01-21T08:03:01.129Z") }
然后您可以在该集合上创建TTL索引。基本上,当scheduledAt成为过去的日期时,MongoDB数据库服务器将定期删除这些文档。
db.scheduledEvents.createIndex( { "scheduledAt": 1 }, { expireAfterSeconds: 30} )
在幕后,有一个在数据库服务器上运行的计划作业,它查询并删除所有这些文档。文件不会立即被删除——有一点延迟,但你应该可以接受。
现在您有了一个调度机制,所以您所需要做的就是从代码中订阅这些事件。要做到这一点,您可以利用Change Streams。
要使用它们,您必须将数据库作为副本集运行(可以是独立的副本集)。然后,在您的应用程序代码中,您可以使用以下代码订阅scheduledEvents集合:
const changeStreamCursor = db.scheduledEvents.watch();
function pollStream(cursor) {
while (!cursor.isExhausted()) {
if (cursor.hasNext()) {
var change = cursor.next();
if(change.operationType === "delete"){
// your logic goes here
}
}
}
pollStream(cursor);
}
pollStream(changeStreamCursor);
显然,scheduledEvents
集合可以包含与业务逻辑相关的其他字段,这些字段可以在变更流侦听器中访问。
从数据库轮询是最简单的方法。若您关心的是避免过于频繁地查询数据库,则可以尝试以下操作。
- 启动基于节点的后端
- 查找未来的第一个日历事件
- 使用setInterval()来安排下一个提醒
- 触发提醒事件后,从#2开始重复
如果您的事件已更新,您可以使用MongoDB的Change Streams来监控更改。更新日历事件后,将其与下一个提醒事件进行比较,如果它在下一个日历提醒之前,则替换下一个提示。
希望这能有所帮助。