Node/Express 应用中延迟超过一小时的触发功能

Trigger function with a delay longer than an hour in a Node/Express app

我想在调用特定端点后延迟 1 小时或 5 小时触发我的 Express 应用程序中的功能。

我已经尝试在我的 enpoint 的 then 链中使用一个简单的 setTimeout,在我的控制器中使用类似这样的东西:

function(req, res, next) {

  return mailer.sendEmail(req.user, 'firstEmail') // returns a promise
  .then(function(emailResult) {
    if (emailResult == 'ok') {
       res.sendStatus(200).json({ message: 'You will receive an email in 1 hour' }) // set positive API json response
    } else {
       res.sendStatus(200).json({ message: 'You will receive an email in 5 hour' }) // set negative API json response
    }
    return emailResult
  })
  .then(function(emailResult){
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            return return mailer.sendEmail(req.user, 'secondEmail')
        }, emailResult == 'ok' ? 60 * 60 * 1000 : 5 * 60 * 60 * 1000) // 1 hour or 5 hours
    })
  }) 
})

似乎可行,但我有两个主要疑问:

有过这样的经验吗?

我已经遇到过这个问题。

我找到的解决方案是使用我的数据库作为时间寄存器。 基本上,如果您使用 SQL 或面向文档的数据库:

  1. 将计划的操作插入数据库。
  2. 每 x 秒检查一次(取决于您需要的准确性)是否有需要弹出的条目。如果是,删除项目,拿走,执行。

您也可以使用 cron 包来做检查,但是...因为这很容易实现,所以您应该自己做。

编辑:为什么是这个解决方案?

首先,这是服务器的 RAM 保护程序,当您有大约 5000 个条目时,您不必将其存储在内存中。

  • 是的,您的所有超时都将被取消,因为它们已存储在内存中
  • 我认为 600 次超时可能不是问题,但您可能会找到更合适的方法,例如对所有超时进行排序的数组和 setInterval 来检查是否需要执行某些操作。

像这样的超时可能是一种解决方案,但不是最好的解决方案。

如果超时会立即添加到您的内存中,例如每小时一次,当您重新启动 Node.js 进程时,尚未触发的计时器将丢失,这意味着您无法重新启动您的应用程序,即使您正在尝试如果您不想丢失任何代码,请更新新代码。丢失电子邮件或永远不会重新启动,有点混乱,对吧?

这种情况下最常实施的方法是消息队列。 你可以把Message Queue当成定时器,在数据库中存储和消费,这样你就不用担心定时器是否被取消或在你不希望发生的时候被多次调用。

RabbitMQ 是一个对 Node.js 友好的独立 MQ。

Kue 是一个依赖 Redis 的类 MQ NPM 包。

希望你喜欢它们。 ;)