Django可能会在不久的将来运行任务

问题描述 投票:9回答:1

假设我有模型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")

现在,当然,关键部分是无论何时onEventElapsed都调用timezone.now() >= event.end。请注意,end可能离当前日期还有几个月的时间。

我已经考虑了两种基本的方法:

  1. 使用定期的cron作业(例如,每五分钟左右),该作业检查在最近五分钟内是否发生了任何事件并执行我的方法。

  2. 使用celery并使用onEventElapsed参数计划eta将来运行(在模型save方法内。

    ]

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

  • 每五分钟检查一次过去五分钟内发生的事件吗?似乎有些动摇,也许某些事件错过了(或者其他事件收到了两次发送的通知?)。可能的工作方式:发送通知后,向模型中添加一个布尔字段,将其设置为True

然后,选项2也有问题:

  • 手动更改事件开始/结束日期时间时的情况。使用celery时,一旦日期更改并发出新任务,就必须存储taskID(easy,ofc)并撤销任务。但是我已经读到,在处理将来运行的任务时,芹菜存在(特定于设计的)问题:Open Issue on github。我意识到这是如何发生的,为什么它只是解决所有问题而已。

现在,我遇到了一些可以潜在地解决我的问题的库:

  • celery_longterm_scheduler(但是这是否意味着我不能像以前那样使用celery,因为Scheduler类不同?这也与django-celery-beat的可能用法联系在一起...使用两个框架中的任何一个,是吗?仍然可以对作业进行排队(它们的运行时间更长一些,但是还没有几个月?)
  • django-apscheduler,使用apscheduler。但是,我找不到任何有关如何处理在不久的将来运行的任务的信息。

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

[[注意:我知道这可能是基于某种观点的,但是,也许有一些我很想念的东西,不管某些人认为它是丑陋还是优雅。

python django celery apscheduler django-celery-beat
1个回答
2
投票
我们在我工作的公司中正在做类似的事情,解决方案非常简单。

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

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

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

    每小时运行一个任务(让我们将此任务称为调度程序任务),该任务将获取下一小时需要发送的所有通知(通过celery beat)-
  1. 通过apply_async(eta)计划这些通知-这将是实际发送的时间
  • 使用该方法可以使您同时获得最佳成绩(eta和节拍)
  • © www.soinside.com 2019 - 2024. All rights reserved.