Celery tasks checklist

Useful checklist for building great Celery tasks. Access Github Repo.
celery; python;
Checks are saved in your local storage

1. Boas Práticas

  • Prefira RabbitMQ ou Redis como broker (nunca use bando de dados relacional como broker de produção)

  • Não use objetos completos em tarefas com parâmetros. Exemplo: Evite objetos Django model:

    # Bom
    @app.task
    def my_task(user_id):
        user = User.objects.get(id=user_id)
        print(user.name)
        # ...
    
    # Ruim
    @app.task
    def my_task(user):
        print(user.name)
        # ...
    
  • Não espere por outras tarefas dentro de uma tarefa.

  • Prefira tarefas indempotentes.

    • "Em matemática e ciência da computação, a idempotência é a propriedade que algumas operações têm de poderem ser aplicadas várias vezes sem que o valor do resultado se altere após a aplicação inicial." - Wikipedia
  • Prefira tarefas atômicas.

    • "Transação Atômica, em ciência da computação, é uma operação, ou conjunto de operações, em uma base de dados, ou em qualquer outro sistema computacional, que deve ser executada completamente em caso de sucesso, ou ser abortada completamente em caso de erro." - Wikipedia
  • Tente novamente quando possível. Mas tenha certeza que as tarefas são indempotentes e atômicos antes de fazê-lo. (Retrying)

  • Defina retry_limit para evitar tarefas quebradas de fazer tentativas infinitas.

  • Exponenciamente caia fora se coisas parecerem que não vão ser corrigidos logo. Jogue um fator randômico para evitar confusão de serviços.

    def exponencial_backoff(task_self):
        minutes = task_self.default_retry_delay / 60
        rand = random.uniform(minutes, minutes * 1.3)
        return int(rand ** task_self.request.retries) * 60
    
    # na tarefa
    raise self.retry(exc=e, countdown=exponencial_backoff(self))
    
    • Para tarefas que requere alto nível de confiabilidade, use acks_late em combinação com retry . Novamente, tenha certeza de que são tarefas idempotentes e atômicas. (Should I use retry or acks_late?)
    • Defina tempos de limite duros e suaves. Recupere graciosamente se as coisas demorarem mais tempo que o esperado.
    from celery.exceptions import SoftTimeLimitExceeded
    
    @app.task(task_time_limit=60, task_soft_time_limit=45)
    def my_task():
        try:
            something_possibly_long()
        except SoftTimeLimitExceeded:
            recover()
    
  • Use múltiplas filas para ter mais controle sobre a taxa de transferência e gerar mais escalabilidade. (Routing Tasks)

  • Estenda a classe de tarefa base para definir comportamentos padrão. (Custom Task Classes)

  • Use recursos da tela para controlar fluxos de tarefas e lidar com concorrência. (Canvas: Designing Work-flows)

2. Monitoração & Testes

  • Faça logging na medida do possível. Use get_task_logger para automaticamente adicionar o nome e o id único da sua task aos logs.
  • No caso de falha, tenha certeza de que os traços de pilha (stack traces) tenham logs e que pessoas sejam notificadas (serviços como Sentry é uma boa idéia).
  • Monitore atividades usando Flower. (Flower: Real-time Celery web-monitor)
  • Use task_aways_eager para testar suas tarefas que estão sendo chamadas.

3. Artigos interessantes:

Yay! You completed the checklist top to bottom!
Now spread the ❤︎ by thanking the author, making improvements or creating you own checklist!