Communitygithub.com

django-celery

Padrões de tarefas assíncronas Django + Celery — configuração, design de tarefas, agendamento com Beat, novas tentativas, workflows canvas, monitoramento e testes. Use ao adicionar jobs em segundo plano, tarefas agendadas ou processamento assíncrono a um app Django.

O que é django-celery?

Este skill fornece padrões de produção para processamento de tarefas em segundo plano em Django usando Celery com Redis ou RabbitMQ. Ele cobre desde a configuração inicial do projeto e definição de tarefas básicas e com retry, até padrões avançados como tarefas idempotentes, limites de tempo flexíveis (soft time limit) e workflows encadeados com Canvas (chain, group, chord). O skill também aborda o agendamento periódico com Celery Beat, tanto via código quanto via banco de dados com django-celery-beat, além de estratégias de tratamento de erros, como fila de mensagens mortas (dead letter queue) e integração com Sentry. Para garantir qualidade, inclui práticas de teste unitário e de integração com `CELERY_TASK_ALWAYS_EAGER`, e oferece uma checklist de produção com recomendações como `CELERY_TASK_ACKS_LATE = True` e monitoramento com Flower. Suporta as plataformas Celery, Django e Redis/RabbitMQ.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/django-celery

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Padrões de Tarefas Assíncronas Django + Celery

Padrões de nível de produção para processamento de tarefas em segundo plano em Django usando Celery com Redis ou RabbitMQ.

Quando Ativar

  • Adicionar jobs em segundo plano ou processamento assíncrono a um app Django
  • Implementar tarefas periódicas/agendadas
  • Descarregar operações lentas (e-mail, geração de PDF, chamadas de API) do ciclo de requisição
  • Configurar Celery Beat para agendamento estilo cron
  • Depurar falhas de tarefas, novas tentativas ou acúmulos na fila
  • Escrever testes para tarefas Celery

Configuração do Projeto

Instalação

pip install 'celery[redis]' django-celery-results django-celery-beat

celery.py — Ponto de Entrada do App

# config/celery.py
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development')

app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()  # Descobre tasks.py em cada INSTALLED_APP

@app.task(bind=True, ignore_result=True)
def debug_task(self):
    print(f'Request: {self.request!r}')
# config/__init__.py
from .celery import app as celery_app

__all__ = ('celery_app',)

Configurações do Django

# config/settings/base.py

# Broker (Redis recomendado para produção)
CELERY_BROKER_URL = env('CELERY_BROKER_URL', default='redis://localhost:6379/0')
CELERY_RESULT_BACKEND = env('CELERY_RESULT_BACKEND', default='django-db')

# Serialização
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

# Comportamento da tarefa
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60        # Limite rígido: 30 min
CELERY_TASK_SOFT_TIME_LIMIT = 25 * 60   # Limite flexível: envia SoftTimeLimitExceeded
CELERY_WORKER_PREFETCH_MULTIPLIER = 1   # Evita que workers acumulem tarefas longas
CELERY_TASK_ACKS_LATE = True            # Re-enfileira tarefas se o worker cair

# Persistência de resultados
CELERY_RESULT_EXPIRES = 60 * 60 * 24   # Mantém resultados por 24 horas

# Agendador Beat (para tarefas periódicas)
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

# Apps instaladas
INSTALLED_APPS += [
    'django_celery_results',
    'django_celery_beat',
]

Executando Workers

# Iniciar worker (desenvolvimento)
celery -A config worker --loglevel=info

# Iniciar agendador Beat (tarefas periódicas)
celery -A config beat --loglevel=info --scheduler django_celery_beat.schedulers:DatabaseScheduler

# Worker + Beat combinados (apenas desenvolvimento, nunca produção)
celery -A config worker --beat --loglevel=info

# Produção: múltiplos workers com concorrência
celery -A config worker --loglevel=warning --concurrency=4 -Q default,high_priority

Padrões de Design de Tarefas

Tarefa Básica

# apps/notifications/tasks.py
from celery import shared_task
import logging

logger = logging.getLogger(__name__)

@shared_task(name='notifications.send_welcome_email')
def send_welcome_email(user_id: int) -> None:
    """Envia e-mail de boas-vindas para usuário recém-registrado."""
    from apps.users.models import User
    from apps.notifications.services import EmailService

    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        logger.warning('send_welcome_email: usuário %s não encontrado', user_id)
        return  # Idempotente — não levanta exceção, tarefa já impossível de completar

    EmailService.send_welcome(user)
    logger.info('E-mail de boas-vindas enviado para o usuário %s', user_id)

Tarefa com Retry

@shared_task(
    bind=True,
    name='integrations.sync_to_crm',
    max_retries=5,
    default_retry_delay=60,       # segundos antes da primeira nova tentativa
    autoretry_for=(ConnectionError, TimeoutError),
    retry_backoff=True,           # backoff exponencial
    retry_backoff_max=600,        # limite de 10 minutos
    retry_jitter=True,            # randomização para evitar efeito manada
)
def sync_contact_to_crm(self, contact_id: int) -> dict:
    """Sincroniza contato com CRM externo com retry em falhas transitórias."""
    from apps.crm.services import CRMClient

    try:
        result = CRMClient().sync(contact_id)
        return result
    except CRMClient.RateLimitError as exc:
        # Atraso específico baseado no cabeçalho da resposta
        raise self.retry(exc=exc, countdown=int(exc.retry_after))

Padrão de Tarefa Idempotente

Projete tarefas para que possam ser executadas com segurança várias vezes com as mesmas entradas:

@shared_task(name='orders.mark_shipped')
def mark_order_shipped(order_id: int, tracking_number: str) -> None:
    """Marca pedido como enviado — seguro executar várias vezes."""
    from apps.orders.models import Order

    updated = Order.objects.filter(
        pk=order_id,
        status=Order.Status.PROCESSING,    # Proteção: só atualiza se ainda não enviado
    ).update(
        status=Order.Status.SHIPPED,
        tracking_number=tracking_number,
    )

    if not updated:
        logger.info('mark_order_shipped: pedido %s já enviado ou não encontrado', order_id)

Tarefa com Limite de Tempo Flexível

from celery.exceptions import SoftTimeLimitExceeded

@shared_task(
    bind=True,
    name='reports.generate_pdf',
    soft_time_limit=120,
    time_limit=150,
)
def generate_pdf_report(self, report_id: int) -> str:
    """Gera relatório PDF com tratamento gracioso de timeout."""
    from apps.reports.services import PDFGenerator

    try:
        path = PDFGenerator.build(report_id)
        return path
    except SoftTimeLimitExceeded:
        # Limpa arquivos parciais antes da interrupção forçada
        PDFGenerator.cleanup(report_id)
        raise

Chamando Tarefas

from datetime import timedelta
from django.utils import timezone

# Fire and forget (assíncrono)
send_welcome_email.delay(user.pk)

# Agendar no futuro
send_reminder.apply_async(args=[user.pk], countdown=3600)  # 1 hora a partir de agora
send_reminder.apply_async(args=[user.pk], eta=timezone.now() + timedelta(days=1))

# Aplicar com roteamento de fila
sync_contact_to_crm.apply_async(args=[contact.pk], queue='high_priority')

# Executar síncrono (testes / depuração apenas)
result = generate_pdf_report.apply(args=[report.pk])

Agendamento com Beat (Tarefas Periódicas)

Agendamento Definido em Código

# config/settings/base.py
from celery.schedules import crontab

CELERY_BEAT_SCHEDULE = {
    'cleanup-expired-sessions': {
        'task': 'users.cleanup_expired_sessions',
        'schedule': crontab(hour=2, minute=0),   # 2h diariamente
    },
    'sync-inventory': {
        'task': 'products.sync_inventory',
        'schedule': 60.0,                         # a cada 60 segundos
    },
    'weekly-digest': {
        'task': 'notifications.send_weekly_digest',
        'schedule': crontab(day_of_week='monday', hour=8, minute=0),
    },
}

Agendamento Definido no Banco (via django-celery-beat)

# Gerencie tarefas periódicas do admin Django ou código
from django_celery_beat.models import PeriodicTask, CrontabSchedule
import json

schedule, _ = CrontabSchedule.objects.get_or_create(
    hour='*/6', minute='0',
    timezone='UTC',
)

PeriodicTask.objects.update_or_create(
    name='Sincronizar inventário a cada 6 horas',
    defaults={
        'crontab': schedule,
        'task': 'products.sync_inventory',
        'args': json.dumps([]),
        'enabled': True,
    }
)

Canvas: Encadeamento e Agrupamento de Tarefas

from celery import chain, group, chord

# Chain: executa tarefas sequencialmente, passando resultados
pipeline = chain(
    fetch_data.s(source_id),
    transform_data.s(),          # recebe o resultado de fetch_data como primeiro argumento
    load_to_warehouse.s(),
)
pipeline.delay()

# Group: executa tarefas em paralelo
parallel = group(
    send_welcome_email.s(user_id)
    for user_id in new_user_ids
)
parallel.delay()

# Chord: tarefas paralelas + callback quando todas completam
result = chord(
    group(process_chunk.s(chunk) for chunk in data_chunks),
    aggregate_results.s(),       # chamada com a lista de resultados dos chunks
)
result.delay()

Tratamento de Erros e Fila de Mensagens Mortas

# apps/core/tasks.py
from celery.signals import task_failure

@task_failure.connect
def on_task_failure(sender, task_id, exception, args, kwargs, traceback, einfo, **kw):
    """Registra todas as falhas de tarefas no Sentry / sistema de alerta."""
    import sentry_sdk
    with sentry_sdk.new_scope() as scope:
        scope.set_context('celery', {
            'task': sender.name,
            'task_id': task_id,
            'args': args,
            'kwargs': kwargs,
        })
        sentry_sdk.capture_exception(exception)
# Roteia tarefas com falha para fila de mensagens mortas após número máximo de tentativas
@shared_task(
    bind=True,
    max_retries=3,
    name='payments.charge_card',
)
def charge_card(self, order_id: int) -> None:
    from apps.payments.models import Order, FailedCharge

    try:
        _do_charge(order_id)
    except Exception as exc:
        if self.request.retries >= self.max_retries:
            # Persiste na tabela de mensagens mortas para revisão manual
            FailedCharge.objects.create(
                order_id=order_id,
                error=str(exc),
                task_id=self.request.id,
            )
            return  # Não levanta — tarefa falhou permanentemente
        raise self.retry(exc=exc)

Testando Tarefas Celery

Teste Unitário (Sem Broker)

# tests/test_tasks.py
import pytest
from unittest.mock import patch, MagicMock
from apps.notifications.tasks import send_welcome_email

class TestSendWelcomeEmail:

    @pytest.mark.django_db
    def test_sends_email_to_existing_user(self, user):
        with patch('apps.notifications.services.EmailService') as mock_email:
            send_welcome_email(user.pk)
            mock_email.send_welcome.assert_called_once_with(user)

    @pytest.mark.django_db
    def test_skips_missing_user_gracefully(self):
        """Não deve levantar exceção quando o usuário é deletado entre o enfileiramento e a execução."""
        send_welcome_email(99999)  # Usuário inexistente — não deve levantar exceção

Teste de Integração com CELERY_TASK_ALWAYS_EAGER

# config/settings/test.py
CELERY_TASK_ALWAYS_EAGER = True      # Executa tarefas síncronamente nos testes
CELERY_TASK_EAGER_PROPAGATES = True  # Re-lança exceções das tarefas

# tests/test_integration.py
@pytest.mark.django_db
def test_registration_triggers_welcome_email(client):
    with patch('apps.notifications.services.EmailService') as mock_email:
        response = client.post('/api/users/', {
            'email': '[email protected]',
            'password': 'strongpass123',
        })

    assert response.status_code == 201
    mock_email.send_welcome.assert_called_once()

Testando Retries

@pytest.mark.django_db
def test_task_retries_on_connection_error():
    with patch('apps.crm.services.CRMClient.sync') as mock_sync:
        mock_sync.side_effect = ConnectionError('timeout')

        with pytest.raises(ConnectionError):
            sync_contact_to_crm.apply(args=[1], throw=True)

        assert mock_sync.call_count == 1  # Apenas primeira tentativa quando eager

Monitoramento

# Inspecionar workers e filas ativos
celery -A config inspect active
celery -A config inspect stats
celery -A config inspect reserved

# Verificar tamanhos das filas (Redis)
redis-cli llen celery

# Flower: monitor web em tempo real
pip install flower
celery -A config flower --port=5555

Anti-Padrões

# RUIM: Passar instâncias de modelos — elas podem estar desatualizadas no momento da execução
send_welcome_email.delay(user)        # Nunca passe objetos ORM
send_welcome_email.delay(user.pk)     # Sempre passe PKs

# RUIM: Chamar tarefas síncronas em views de produção
result = generate_report.apply()      # Bloqueia a thread da requisição

# RUIM: Tarefa não idempotente sem proteções
@shared_task
def charge_and_fulfill(order_id):
    order.charge()     # Pode cobrar duas vezes se a tarefa for repetida!
    order.fulfill()

# BOM: Idempotente com proteção de status
@shared_task
def charge_and_fulfill(order_id):
    order = Order.objects.select_for_update().get(pk=order_id)
    if order.status != Order.Status.PENDING:
        return  # Já processado
    order.charge()
    order.fulfill()

Checklist de Produção

VerificaçãoConfiguração
Reinicialização do worker ao cairUnidade supervisord ou systemd
CELERY_TASK_ACKS_LATE = TrueRe-enfileira tarefas se o worker cair
CELERY_WORKER_PREFETCH_MULTIPLIER = 1Distribuição justa de tarefas longas
Filas separadas por prioridade-Q default,high_priority,low_priority
CELERY_TASK_SOFT_TIME_LIMIT definidoTimeout gracioso antes da interrupção forçada
Integração com SentryCapturar todos os sinais task_failure
Flower ou outro monitorVisibilidade sobre profundidade das filas
Beat executado em um único nóEvita execução duplicada de tarefas agendadas

Skills Relacionados

  • django-patterns — ORM, camada de serviço e estrutura do projeto
  • django-tdd — Testando modelos, views e serviços Django
  • python-testing — Configuração de pytest e fixtures

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Habilidades Relacionadas