我创建了一个django应用程序,其中包含一个组织数据库表的芹菜任务。芹菜任务大约需要8秒来完成这项工作(在超过100万行中进行相当繁重的表移动和查找)
这个芹菜是通过注册用户点击按钮开始的。
我在views.py中创建了一个任务视图,在urls.py中创建了单独的任务url。当导航到此任务url时,任务开始。
我的问题:
- 当任务未完成时刷新任务url时,将启动一个新任务
- 使用此设置,您可以导航到另一个页面或重新加载视图
如何防止每次刷新时任务启动,并防止导航到另一个页面。理想情况下,用户只能运行一个这种特定类型的任务。
这在JQuery/Ajax中可行吗?我不是专家,也没有使用JQuery/Ajax的经验,有什么英雄能为我指明正确的方向吗。
感谢
"如何防止每次刷新时任务启动">
首先确保使用"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返回,"请等待"页面每X秒调用一次该视图(使用ajax)以更新自己(并可能在任务完成时将用户重定向到下一个页面)。
现在,如果用户在任务运行时无法执行某些操作(除了重新启动相同的任务),则可以对这些操作使用相同的"检查当前任务的会话"机制(使其成为视图装饰器确实很有帮助)。
我相信在服务器端使用锁可以更容易地完成这项工作,请参阅以下问题:运行"独特的";使用芹菜的任务
如果需要在客户端进行,可能的方法是设置类似的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 });
}
任务完成时删除