Django +后台任务如何初始化

时间:2018-05-16 14:55:23

标签: python django background-task

我有一个基本的django项目,我用它作为(Condor)计算集群的前端接口来生成模拟。用户可以从django应用程序开始模拟(在Condor中)。模拟相关的元数据和模拟状态保存在DB中。

我需要添加一个新功能:在(某些)模拟完成时发出通知。

由于我想要一个简单的解决方案(我已经在使用后台任务),我想使用重复任务,在固定的时间间隔查询Condor有关任务,更新数据库,并在必要时发送通知。

因此,如果我想每10分钟更新一次这种状态,我将会有:

@background(schedule=1)
def check_simulations(repeat=600):
    # lookup simulation statuses
    simulation_list = get_Simulations()
    for sim in simulations_list:
       if sim.status == Simulation.DONE:
            user.email_user('Simulation Complete', 'You have been notified')

def initialize():
     check_simulations()

然而,必须启动(或更好地说是initialize()方法)来创建和调度check_simulations()任务(这将实际上序列化调用并将其保存在DB中);之后,后台任务线程将读取并执行并重新安排它(如果有错误)

我的问题:

  • 我应该将对initialize()方法的调用仅运行一次吗?

一个这样的地方可能是例如urls.py,但这是一个非常难看的解决方案。还有更好的方法吗?

  • 如何确保服务器重启不会创建和安排新任务(如果已存在) 如果已经安排了任务(因此序列化任务在后台任务表中)并且重新启动了Web服务器,那么可能会发生这种情况,因此再次调用initialize()方法以创建和安排新任务...

2 个答案:

答案 0 :(得分:1)

我有一个类似的问题,我用这种方式解决了。

我在urls.py中初始化我的任务,我不知道您是否可以使用其他位置来放置它,还要添加它,以及是否要检查该任务是否已经在数据库中

from background_task.models import Task
if not Task.objects.filter(verbose_name="update_orders").exists():
   tasks.update_orders(repeat=300, verbose_name="update_orders")

我已经对其进行了测试,并且效果很好,您还可以使用其他参数(例如name,hash,...)搜索订单。

您可以在此处检查任务模型:https://github.com/arteria/django-background-tasks/blob/master/background_task/models.py

答案 1 :(得分:0)

从官方文档中,后台任务可以由background装饰器初始化,如下所示

from background_task import background
from django.contrib.auth.models import User

@background(schedule=60)
def notify_user(user_id):
    # lookup user by id and send them a message
    user = User.objects.get(pk=user_id)
    user.email_user('Here is a notification', 'You have been notified')


Q.1 :哪里是完成这些任务的最佳位置? 你可以把它写在任何python模块/文件的任何地方。在我看来,创建一个模块task.py并将这些任务函数放在那里。 task.py更有意义,对吧?

Q.2 :如何避免重复任务?
来自doc

  

当重复任务成功完成时,带有一个新任务   计划重复的偏移量。另一方面,如果重复任务   失败并且没有重新启动,重复链就停止了。

因此我认为没有机会生成重复的任务