如何判断任务是否已在django芹菜中排队?
以下是我的设置:如何判断任务是否已在django芹菜中排队?,django,message-queue,celery,django-celery,Django,Message Queue,Celery,Django Celery,以下是我的设置: django 1.3 芹菜2.2.6 django芹菜2.2.4 djkombu 0.9.2 在我的settings.py文件中 BROKER_BACKEND = "djkombu.transport.DatabaseTransport" i、 我只是在用数据库把任务排成队列 现在谈谈我的问题:我有一个用户发起的任务,可能需要几分钟才能完成。我希望每个用户只运行一次任务,并将任务结果缓存在临时文件中,因此如果用户再次启动任务,我只返回缓存的文件。我的视图函数中有如下代码:
- django 1.3
- 芹菜2.2.6
- django芹菜2.2.4
- djkombu 0.9.2
BROKER_BACKEND = "djkombu.transport.DatabaseTransport"
i、 我只是在用数据库把任务排成队列
现在谈谈我的问题:我有一个用户发起的任务,可能需要几分钟才能完成。我希望每个用户只运行一次任务,并将任务结果缓存在临时文件中,因此如果用户再次启动任务,我只返回缓存的文件。我的视图函数中有如下代码:
task_id = "long-task-%d" % user_id
result = tasks.some_long_task.AsyncResult(task_id)
if result.state == celery.states.PENDING:
# The next line makes a duplicate task if the user rapidly refreshes the page
tasks.some_long_task.apply_async(task_id=task_id)
return HttpResponse("Task started...")
elif result.state == celery.states.STARTED:
return HttpResponse("Task is still running, please wait...")
elif result.state == celery.states.SUCCESS:
if cached_file_still_exists():
return get_cached_file()
else:
result.forget()
tasks.some_long_task.apply_async(task_id=task_id)
return HttpResponse("Task started...")
这段代码几乎可以工作。但是当用户快速重新加载页面时,我遇到了一个问题。从任务排队到最终将任务从队列中拉出并交给工作人员之间有1-3秒的延迟。在此期间,任务的状态保持挂起状态,这会导致视图逻辑启动重复任务
我需要的是某种方法来判断任务是否已经提交到队列中,这样我就不会再提交两次。在芹菜中有没有标准的方法 您可以通过将结果手动存储在数据库中来作弊。让我解释一下这会有什么帮助 例如,如果使用RDBMS(带列的表-任务id、状态、结果): 视图部分:
我和Redis一起解决了这个问题。只需在redis中为每个任务设置一个键,然后在任务的after_return方法中从redis中删除该键。Redis是轻量级和快速的。我不认为(正如Tomek和其他人所建议的那样)使用数据库是实现这种锁定的方法。django有内置的缓存框架,该框架应足以完成此锁定,并且必须更快。见:
Django可以配置为使用
memcached
作为其缓存后端,这可以分布在多台机器上。。。我觉得这样更好。想法?能否再次启动长任务()?如果是这样的话,这可能是一个足够的延迟,可以防止用户和芹菜之间的竞争情况。再次启动长任务()不会导致重复任务。我更新了我的示例,以显示代码将在何处执行重复任务。这不是我的问题。可以再次启动长任务吗()
检查并等待任务在完成之前是否已移出挂起状态?当然可以,但这似乎无法完成任何事情。forget()删除结果并将任务放回挂起状态,因此我们已经“知道”状态,除非出现另一个不太可能的争用条件。在考虑较小的边缘情况之前,我想先解决我的原始问题。如果无法看到挂起状态(因为您一直等到它通过),那么您的问题就解决了,对吗?还是有别的事情发生了?一个很好的解决方案,正是我想要的。谢谢你的链接!