按钮单击只运行芹菜任务一次

时间:2017-11-02 12:43:00

标签: jquery python ajax django celery

我创建了一个带有芹菜任务的django应用程序,用于组织数据库表。芹菜任务需要大约8秒才能完成这项任务(非常繁重的表格移动和查找超过100万行)

这种芹菜通过注册用户点击按钮开始。

我在views.py中创建了一个任务视图,在urls.py中创建了一个单独的task-url。导航到此任务URL时,任务开始。

我的问题:

  1. 当任务未完成时刷新task-url时,您将启动一个新任务。
  2. 通过此设置,您可以导航到其他页面或重新加载视图
  3. 如何防止每次刷新时启动任务并阻止导航到其他页面。理想情况下,用户只能运行此特定类型的一个任务。

    这可能适用于JQuery / Ajax吗?有些英雄会指出我正确的方向,因为我不是专家,对JQuery / Ajax没有经验。

    由于

2 个答案:

答案 0 :(得分:1)

  

“如何在每次刷新时阻止任务启动”

首先确保使用“POST / redirect / GET”模式:您的视图应仅在“POST”请求中触发任务(GET请求必须没有副作用),并且然后返回HttpResponseRedirect

这不会阻止用户在第一个任务仍在运行时触发第二个任务,但 会阻止每次刷新(“GET”)页面时重新提交表单。 ..

  

理想情况下,用户只能运行此特定类型的一个任务。

在触发任务时,将其ID存储在会话中,触发任务之前检查会话以查找任务ID。如果有,请使用它来检查任务的状态。如果已完成(无论结果如何),请删除任务ID并继续执行新任务,否则只显示一条消息,告诉用户他已经有任务正在运行。

请确保你在会话中正确处理“ghost”task_id的情况(这可能是一个长期完成的任务,芹菜已经丢弃了结果,或者在工人或经纪人崩溃中丢失的任务 - 是的,sh!t发生 - 等等)。一个有效的解决方案是实际存储(timestamp, task_id)对,如果芹菜没有task_id的状态   - 实际上“无状态”是(错误)命名为celery.states.PENDING,这实际上意味着“我对这个任务的状态ATM没有任何线索” - 检查时间戳。如果它的方式比它应该的那么大,那么你可以认为它已经很久了,还有6英尺以下。

  

并阻止导航到另一个页面。

为什么你想阻止你的用户在此期间做其他事情呢?从UI / UX的角度来看,一旦任务被触发,您的用户应该被重定向到“请稍候”页面(尽可能多)一些进度条或类似的反馈。这里简单(如果有点重)解决方案是使用ajax进行一些轮询:你设置一个视图,它接受一个task_id,检查结果/进度并将它们作为json返回,并且'please wait'页面调用这个视图(使用ajax )每X秒更新一次(并且可能在完成任务时将用户重定向到下一页)。

现在,如果有一些操作(除了重新启动相同的任务),您的用户在任务运行时无法执行,您可以对这些操作使用相同的“检查当前任务的会话”机制(制作它是视图装饰者真的有帮助。)

答案 1 :(得分:0)

我相信使用锁可以更容易地在服务器端完成,请参阅此问题Running "unique" tasks with celery

如果需要在客户端完成,可能的方法是设置像这样的cookie

if (typeof $.cookie("running") === "undefined"){
  var date = new Date();
  var minutes = 20;
  date.setTime(date.getTime() + (minutes * 60 * 1000));
  $.cookie("running", "true", { expires: date });
}

并在任务完成时删除