Django 运行 任务(可能)在遥远的未来

Django run tasks (possibly) in the far future

假设我有一个模型Event。我想在活动结束后向所有受邀用户发送通知(电子邮件、推送等)。大致如下:

class Event(models.Model):
    start = models.DateTimeField(...)
    end = models.DateTimeField(...)
    invited = models.ManyToManyField(model=User)

    def onEventElapsed(self):
        for user in self.invited:
           my_notification_backend.sendMessage(target=user, message="Event has elapsed")

现在,当然,关键部分是每当 timezone.now() >= event.end 时调用 onEventElapsed。 请记住,end 可能距离当前日期还有几个月。

我想过两种基本的方法:

  1. 使用周期性的 cron 作业(例如,每五分钟左右)检查过去五分钟内是否有任何事件发生并执行我的方法。

  2. 使用 celery 并使用 eta 参数安排 onEventElapsed 将来成为 运行(在模型 save 中方法).

考虑选项 1,可能的解决方案可能是 django-celery-beat。但是,运行 以固定时间间隔发送通知的任务似乎有点奇怪。此外,我提出了一个(潜在的)问题,该问题(可能)会导致一个不太优雅的解决方案:

话又说回来,选项2也有问题:

现在,我遇到了一些可能会解决我的问题的库:

我处理这个问题的方式是否存在根本性缺陷?我很高兴收到您的任何意见。

注意:我知道这可能是基于某种观点,但是,也许有一个非常基本的东西我错过了,不管有些人认为它是丑陋的还是优雅的。

我所在的公司正在做这样的事情,解决方法也很简单。

让 cron / celery 每小时 运行 节拍一次,以检查是否需要发送任何通知。 然后发送这些通知并将它们标记为已完成。这样,即使您的通知时间提前了数年,它仍会发送。使用 ETA 不是等待很长时间的方法,您的缓存/amqp 可能会丢失数据。

您可以根据需要减少间隔时间,但请确保它们不重叠。

如果一个小时的时差太大,那么你可以做的是,运行每小时一个调度程序。逻辑类似于

  1. 运行 一个任务(让我们称之为调度程序任务)每小时获取所有需要在下一个小时内发送的通知(通过 celery beat)-
  2. 通过 apply_async(eta) 安排这些通知 - 这将是实际发送

使用该方法将使您获得最佳世界(eta 和节拍)