AsyncResult(task_id)返回"PENDING"状态,即使任务已开始

9 投票
3 回答
5016 浏览
提问于 2025-04-18 11:47

在这个项目中,我尝试去检查一个长时间运行的任务的状态,并更新它的运行状态。在开发环境中这个方法是有效的,但当我把项目放到生产服务器上时,就不行了。我一直看到状态是'PENDING',即使我能在flower上看到任务已经开始。不过,当任务完成时,我还是能获取到更新的结果,这时任务状态是'SUCCESS'。我在生产环境中使用的是Python 2.6、Django 1.6和Celery 3.1,结果后端是AMQP。

@csrf_exempt
def poll_state(request):
    data = 'Fail'

    if request.is_ajax():
            if 'task_id' in request.POST.keys() and request.POST['task_id']:
                    task_id = request.POST['task_id']
                    email = request.POST['email']
                    task = AsyncResult(task_id)
                    print "task.state=", task.state
                    if task.state == 'STARTED':
                            task_state = 'Running'
                            data = 'Running'
                            #data = 'Running'
                    elif task.state == 'PENDING' or task.state == 'RETRY':
                            task_state = 'Waiting'
                            data = 'Pending'
                    elif task.state == 'SUCCESS':
                            task_state = 'Finished'
                            if task.result:
                                    data = task.result
                            else:
                                    data = 'None'

                    else:
                            task_state = task.state
                            data = 'Error'
                            print 'data status =', task_state
            else:
                    task_state = task.state
                    data = 'Error'
    else:
            task_state = task.state
            data = "Error"

    json_data = json.dumps({'task_state':task_state, 'task_data':data})

 return HttpResponse(json_data, mimetype='application/json')

另外,flower总是显示工作者的状态为离线,但任务的状态是正确的。当使用celery events 3.1.12(Cipater)时,它显示的工作者状态是正确的。

3 个回答

0

对于使用 django-celery-email 的朋友们,必须设置以下内容:

CELERY_EMAIL_TASK_CONFIG = {
    'name': 'djcelery_email_send',
    'ignore_result': False,
}

CELERY_TASK_TRACK_STARTED = True
CELERY_EMAIL_CHUNK_SIZE = 1 

我认为我遇到的类似问题是因为 'ignore_result' 被设置为 True。根据 django-celery-email 的文档:

结果将是一个包含 celery AsyncResult 对象的列表,你可以选择忽略它们,或者用它们来检查邮件发送任务的状态,甚至可以等到它完成。如果你想使用这些功能,你需要启用结果后端,并在 CELERY_EMAIL_TASK_CONFIG 中将 ignore_result 设置为 False。如果你关心任务的状态和结果,还应该在设置中将 CELERY_EMAIL_CHUNK_SIZE 设置为 1。

希望这能帮助到其他人,我也花了好几个小时才搞明白这个问题……

11

对于Celery 4.1.0和Django 1.11.7,你在config.py文件中需要这样设置:

正确的写法:

task_track_started = True

也可以这样写:

CELERY_TASK_TRACK_STARTED = True

错误的写法:

CELERY_TRACK_STARTED = True

我花了两个小时才搞明白这个,希望这能帮助到将来需要的人。

3

这可能和 CELERY_TRACK_STARTED 这个设置有关。根据文档的说明:

CELERY_TRACK_STARTED

如果设置为 True,当任务被工作者执行时,它会报告状态为“已开始”。默认值是 False,因为正常情况下不需要报告这么详细的状态。任务通常只有三种状态:待处理、已完成或等待重试。设置“已开始”状态在处理一些需要很长时间的任务时会很有用,这样可以知道当前正在运行的是哪个任务。

也许你在开发环境中把 CELERY_TRACK_STARTED = True 设置了,但在生产环境中没有?

撰写回答