【问题标题】:Django schedule task on timeoutDjango计划任务超时
【发布时间】:2011-09-12 16:23:32
【问题描述】:

我在我的数据库中的一个实体上设置了超时,并为其分配了一个状态(活动/已完成)。我想要的是在超时到期时将该实体的状态更改为完成。我正在考虑使用 celery 创建一个与对象创建相关的超时的计划任务,这反过来会触发一个 django 信号来通知对象已“过期”,然后我会将值设置为完成信号处理程序。尽管如此,这似乎有点开销,我认为必须有一种更直接的方法来做到这一点。

提前谢谢你。

【问题讨论】:

    标签: django scheduled-tasks celery


    【解决方案1】:

    不一定是轻量级,但是当我遇到这个问题时,我有两种解决方案。

    首先,我编写了一个 Django 管理器,它会创建一个“即将过期”对象的查询集,然后删除它们。为了使这更轻松,我将“事件过期”对象保留在他们自己的表中,并与实际对象一对一关系,并删除他们为保留而完成的这些事件那张桌子很小。 “将过期”对象和被标记为“过期”的对象之间的关系只会在您取消引用 ForeignKey 字段时导致第二个表上的数据库命中,因此它相当轻量级。然后,我会每 5 分钟使用 cron(Unix 的调度管理器,如果您不熟悉 Unix)调用一次管理调用。对于每隔一小时左右的超时,这很好。

    对于更接近秒的超时,我的解决方案是运行一个单独的服务器,该服务器通过来自 Django 应用程序的 REST 调用接收超时通知。它保留了超时发生时间的排序列表,然后调用上述管理调用。它基本上是一个自己的调度程序,由 Django 进程提供给它的预定事件。为了便宜,我使用 Node.js 编写它。

    这两种方法都有效。 cron 工作要容易得多。

    【讨论】:

    • 感谢您的解决方案。尽管如此,第一个比我对这个特定任务所需的准确度有点低,第二个似乎比我最初的 celery 方法有更多的开销。
    【解决方案2】:

    如果状态在过期之前一直处于活动状态并且之后总是完成,那么只有一个“已完成”的日期时间字段会更简单。过去有日期时间的所有内容都将完成,未来的所有内容都将处于活动状态。除非您的问题中没有提到某些复杂性,否则它应该提供您想要的功能,而无需任何安排。

    例子:

    class TaskManager(models.Manager):
        def finished(self):
            return self.filter(finish__lte=datetime.datetime.now())
    
        def active(self):
            return self.filter(finish__gt=datetime.datetime.now())
    
    class Task(models.Model):
        finish = models.DateTimeField()
    
        def is_finished(self):
            return self.finish <= datetime.datetime.now()
    

    【讨论】:

    • 是的,你说得很好,但确实有一些额外的功能需要调度(即我使用彗星服务器通知活动用户会话对象已过期)。实际上,我最终完成了 celery 实现,我对它的工作方式和它引入的复杂性非常满意(实际上还不错)。我还喜欢这样一个事实,即对我的架构的影响很小,因为它允许我使用 django 信号保持它的松散耦合,并将所有 celery 的东西保存在一个单独的模块中。
    猜你喜欢
    • 2019-06-06
    • 1970-01-01
    • 2021-04-19
    • 2017-09-22
    • 2014-12-10
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 2020-06-15
    相关资源
    最近更新 更多