在Flask成功提交后执行芹菜任务?

时间:2017-10-13 18:31:37

标签: flask transactions celery race-condition

相对长时间运行的任务被委托给另一台服务器上单独运行的芹菜工作者。

但是,结果会被添加回关系数据库(表格根据task_descr.id更新为关键,见下文),工作人员使用ignore_result

Flask应用程序要求的任务:

task = app.celery.send_task('tasks.mytask', [task_descr.id, attachments])

问题是在Flask端尚未关闭事务时请求任务。这会导致竞争条件,因为有时芹菜工作者会在Flask app中的事务结束前完成任务。

仅在成功交易后发送任务的正确方法是什么?

或者工作人员在尝试条件task_descr.id之前检查UPDATE可用性并重试任务(这感觉太复杂了)?

Run function after a certain type of model is committed的回答讨论了类似的情况,但这里的任务发送是明确的,所以不需要在某些模型中监听更新/插入。

1 个答案:

答案 0 :(得分:0)

其中一个方法是Per-Request After-Request Callbacks,感谢Armin Ronacher:

from flask import g

def after_this_request(func):
    if not hasattr(g, 'call_after_request'):
        g.call_after_request = []
    g.call_after_request.append(func)
    return func


@app.after_request
def per_request_callbacks(response):
    for func in getattr(g, 'call_after_request', ()):
        response = func(response)
    return response

就我而言,用法是:

    @after_this_request
    def send_mytask(response):
        if response.status_code in {200, 302}:
            task = app.celery.send_task('tasks.mytask', [task_descr.id, attachments])
        return response

不理想,但似乎有效。我的任务仅适用于成功提供的请求,因此我不关心500或其他错误情况。