Celery在Django / Python中的任务最佳实践

时间:2014-08-03 13:25:16

标签: python django celery

考虑一个需要异步完成繁重工作的函数。呼叫客户端可以立即恢复缓存版本,也可以重新收到数字正在被压缩的响应(对客户端的有效响应)。

以下代码段是否适用于此模式?

from django.core import cache
from proj.celery import app

class SomeModel(models.Model):
    # ...
    def get_crunched_numbers(self):
        cache_key = 'foo:{}'.format(self.id)
        res = cache.get(cache_key)
        if not res:
            @app.task
            def gen_crunched_numbers():
                res = do_heavy_lifting()
                cache.set(cache_key, res)
                return res
            gen_crunched_numbers.delay()
            return 'crunching... come back later'
        else:
            return res

是否有更好的替代方法来运行像这样的Celery任务,同时在一段代码中包含所有逻辑?

修改:如评论中所述,此代码甚至无法正常工作。因此,任何关于良好模式的建议都是非常有必要的。

1 个答案:

答案 0 :(得分:2)

您的代码看起来很混乱。为什么不在类之外定义芹菜任务函数并将其称为:

from django.core import cache
from proj.celery import app

class SomeModel(models.Model):
    # ...
    def get_crunched_numbers(self):
        cache_key = 'foo:{}'.format(self.id)
        res = cache.get(cache_key)
        if not res:
            gen_crunched_numbers.delay(cache_key)
            return 'crunching... come back later'
        else:
            return res

@app.task
def gen_crunched_numbers(cache_key):
    res = do_heavy_lifting()
    cache.set(cache_key, res)
    return res

此外,我通常更喜欢使用bind=True创建任务:

@app.task(bind=True)
def gen_crunched_numbers(self, cache_key):
    res = do_heavy_lifting()
    cache.set(cache_key, res)
    return res

通过self.request,我可以访问task context。例如,根据通过芹菜或直接调用函数来改变行为:

@app.task(bind=True)
def gen_crunched_numbers(self, cache_key):
    res = do_heavy_lifting()
    cache.set(cache_key, res)
    if self.request.called_directly:
        return res
    else:
        return { 'result': res, 'cache': cache_key }