Communitygithub.com

django-celery

Django + Celery の非同期タスクパターン — 設定、タスク設計、Beat スケジューリング、リトライ、Canvas ワークフロー、監視、テスト。Django アプリにバックグラウンドジョブ、定期タスク、非同期処理を追加する際に使用します。

django-celery とは?

このスキルは、Django アプリケーションで Celery と Redis または RabbitMQ を使用した本番環境向けのバックグラウンドタスク処理パターンを提供します。タスクの設定、設計、呼び出し、エラーハンドリング、Canvas によるチェーン/グループ/コード、django-celery-beat を使用した定期タスクのスケジューリング、テスト戦略、監視手法を網羅しています。特に、べき等性、リトライバックオフ、デッドレターキュー、ソフトタイムリミットといった実践的なパターンに重点を置いています。このスキルは、Claude Code、Cursor、Codex などの AI エージェントが Django + Celery の堅牢な非同期処理実装を指示する際に利用できます。

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

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Django + Celery 非同期タスクパターン

Redis または RabbitMQ を使用し、Django で Celery を用いた本番環境向けバックグラウンドタスク処理のパターン。

いつアクティブにするか

  • Django アプリにバックグラウンドジョブや非同期処理を追加するとき
  • 定期的・スケジュールされたタスクを実装するとき
  • リクエストサイクルから低速な処理(メール、PDF 生成、API 呼び出し)をオフロードするとき
  • Celery Beat で cron 風のスケジューリングを設定するとき
  • タスクの失敗、リトライ、キューのバックログをデバッグするとき
  • Celery タスクのテストを書くとき

プロジェクトセットアップ

インストール

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

celery.py — アプリエントリーポイント

# 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()  # INSTALLED_APP 内の tasks.py を自動検出

@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',)

Django 設定

# config/settings/base.py

# ブローカー(本番では Redis 推奨)
CELERY_BROKER_URL = env('CELERY_BROKER_URL', default='redis://localhost:6379/0')
CELERY_RESULT_BACKEND = env('CELERY_RESULT_BACKEND', default='django-db')

# シリアライゼーション
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

# タスクの動作
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60        # ハードリミット: 30分
CELERY_TASK_SOFT_TIME_LIMIT = 25 * 60   # ソフトリミット: SoftTimeLimitExceeded を送出
CELERY_WORKER_PREFETCH_MULTIPLIER = 1   # ワーカーが長時間タスクを占有するのを防ぐ
CELERY_TASK_ACKS_LATE = True            # ワーカークラッシュ時にキューに再投入

# 結果の保持
CELERY_RESULT_EXPIRES = 60 * 60 * 24   # 結果を24時間保持

# Beat スケジューラー(定期タスク用)
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

# インストール済みアプリ
INSTALLED_APPS += [
    'django_celery_results',
    'django_celery_beat',
]

ワーカーの起動

# ワーカー起動(開発)
celery -A config worker --loglevel=info

# Beat スケジューラー起動(定期タスク)
celery -A config beat --loglevel=info --scheduler django_celery_beat.schedulers:DatabaseScheduler

# ワーカー + Beat 統合(開発のみ、本番では非推奨)
celery -A config worker --beat --loglevel=info

# 本番: マルチワーカー、並行実行
celery -A config worker --loglevel=warning --concurrency=4 -Q default,high_priority

タスク設計パターン

基本タスク

# 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:
    """新規登録ユーザーにウェルカムメールを送信する。"""
    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: ユーザー %s が見つかりません', user_id)
        return  # べき等 — タスクは既に完了不可能なので送出しない

    EmailService.send_welcome(user)
    logger.info('ウェルカムメールをユーザー %s に送信しました', user_id)

リトライ可能なタスク

@shared_task(
    bind=True,
    name='integrations.sync_to_crm',
    max_retries=5,
    default_retry_delay=60,       # 初回リトライまでの秒数
    autoretry_for=(ConnectionError, TimeoutError),
    retry_backoff=True,           # 指数バックオフ
    retry_backoff_max=600,        # 最大10分
    retry_jitter=True,            # ランダム化して輻輳を防止
)
def sync_contact_to_crm(self, contact_id: int) -> dict:
    """一時的な障害でリトライ可能な、外部CRMへの連絡先同期。"""
    from apps.crm.services import CRMClient

    try:
        result = CRMClient().sync(contact_id)
        return result
    except CRMClient.RateLimitError as exc:
        # レスポンスヘッダーから具体的なリトライ遅延を設定
        raise self.retry(exc=exc, countdown=int(exc.retry_after))

べき等タスクパターン

同じ入力で安全に複数回実行できるようにタスクを設計する:

@shared_task(name='orders.mark_shipped')
def mark_order_shipped(order_id: int, tracking_number: str) -> None:
    """注文を発送済みにマーク — 複数回実行しても安全。"""
    from apps.orders.models import Order

    updated = Order.objects.filter(
        pk=order_id,
        status=Order.Status.PROCESSING,    # ガード: まだ発送済みでない場合のみ更新
    ).update(
        status=Order.Status.SHIPPED,
        tracking_number=tracking_number,
    )

    if not updated:
        logger.info('mark_order_shipped: 注文 %s は既に発送済みまたは見つかりません', order_id)

ソフトタイムリミット付きタスク

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:
    """グレースフルなタイムアウト処理付きPDFレポート生成。"""
    from apps.reports.services import PDFGenerator

    try:
        path = PDFGenerator.build(report_id)
        return path
    except SoftTimeLimitExceeded:
        # ハードキル前に部分ファイルをクリーンアップ
        PDFGenerator.cleanup(report_id)
        raise

タスクの呼び出し

from datetime import timedelta
from django.utils import timezone

# ファイアアンドフォーゲット(非同期)
send_welcome_email.delay(user.pk)

# 将来のスケジュール
send_reminder.apply_async(args=[user.pk], countdown=3600)  # 1時間後
send_reminder.apply_async(args=[user.pk], eta=timezone.now() + timedelta(days=1))

# キュールーティング付きで適用
sync_contact_to_crm.apply_async(args=[contact.pk], queue='high_priority')

# 同期的に実行(テスト/デバッグのみ)
result = generate_pdf_report.apply(args=[report.pk])

Beat スケジューリング(定期タスク)

コード定義のスケジュール

# 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),   # 毎日午前2時
    },
    'sync-inventory': {
        'task': 'products.sync_inventory',
        'schedule': 60.0,                         # 60秒ごと
    },
    'weekly-digest': {
        'task': 'notifications.send_weekly_digest',
        'schedule': crontab(day_of_week='monday', hour=8, minute=0),
    },
}

データベース定義のスケジュール(django-celery-beat 経由)

# Django 管理画面またはコードから定期タスクを管理
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='6時間ごとに在庫を同期',
    defaults={
        'crontab': schedule,
        'task': 'products.sync_inventory',
        'args': json.dumps([]),
        'enabled': True,
    }
)

Canvas: タスクのチェーンとグループ化

from celery import chain, group, chord

# チェーン: タスクを順次実行し、結果を渡す
pipeline = chain(
    fetch_data.s(source_id),
    transform_data.s(),          # fetch_data の結果を最初の引数として受け取る
    load_to_warehouse.s(),
)
pipeline.delay()

# グループ: タスクを並列実行
parallel = group(
    send_welcome_email.s(user_id)
    for user_id in new_user_ids
)
parallel.delay()

# Chord: 並列タスク + 全完了時のコールバック
result = chord(
    group(process_chunk.s(chunk) for chunk in data_chunks),
    aggregate_results.s(),       # チャンク結果のリストで呼び出される
)
result.delay()

エラーハンドリングとデッドレターキュー

# 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):
    """すべてのタスク失敗を Sentry / アラートに記録する。"""
    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)
# 最大リトライ後に失敗タスクをデッドレターキューにルーティング
@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:
            # 手動再確認用にデッドレターテーブルに永続化
            FailedCharge.objects.create(
                order_id=order_id,
                error=str(exc),
                task_id=self.request.id,
            )
            return  # 送出しない — タスクは永続的に失敗
        raise self.retry(exc=exc)

Celery タスクのテスト

ユニットテスト(ブローカーなし)

# 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):
        """エンキューと実行の間にユーザーが削除されても送出しない。"""
        send_welcome_email(99999)  # 存在しないユーザー — 送出してはならない

CELERY_TASK_ALWAYS_EAGER を使った統合テスト

# config/settings/test.py
CELERY_TASK_ALWAYS_EAGER = True      # テストではタスクを同期的に実行
CELERY_TASK_EAGER_PROPAGATES = True  # タスクの例外を再送出

# 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()

リトライのテスト

@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  # eager の場合は最初の試行のみ

監視

# アクティブなワーカーとキューを検査
celery -A config inspect active
celery -A config inspect stats
celery -A config inspect reserved

# キューの長さを確認(Redis)
redis-cli llen celery

# Flower: Webベースのリアルタイムモニター
pip install flower
celery -A config flower --port=5555

アンチパターン

# BAD: モデルインスタンスを渡す — 実行時には古くなっている可能性がある
send_welcome_email.delay(user)        # ORM オブジェクトは渡さない
send_welcome_email.delay(user.pk)     # 常に PK を渡す

# BAD: 本番ビューでタスクを同期的に呼び出す
result = generate_report.apply()      # リクエストスレッドをブロックする

# BAD: ガードなしの非べき等タスク
@shared_task
def charge_and_fulfill(order_id):
    order.charge()     # タスクがリトライされると二重請求される可能性がある!
    order.fulfill()

# GOOD: ステータスガード付きべき等
@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  # 既に処理済み
    order.charge()
    order.fulfill()

本番チェックリスト

チェック項目設定
ワーカーのクラッシュ時再起動supervisord または systemd ユニット
CELERY_TASK_ACKS_LATE = Trueワーカークラッシュ時にタスクをキューに再投入
CELERY_WORKER_PREFETCH_MULTIPLIER = 1長時間タスクの公平な分散
優先度別の個別キュー-Q default,high_priority,low_priority
CELERY_TASK_SOFT_TIME_LIMIT を設定ハードキル前のグレースフルなタイムアウト
Sentry 統合すべての task_failure シグナルをキャプチャ
Flower または他のモニターキューの深さを可視化
Beat は単一ノードでのみ実行スケジュールされたタスクの重複実行を防止

関連スキル

  • django-patterns — ORM、サービスレイヤー、プロジェクト構造
  • django-tdd — Django モデル、ビュー、サービスのテスト
  • python-testing — pytest の設定とフィクスチャ

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.

関連スキル