Для роботи Celery нам знадобиться база даних Redis.

Встановлення Redis.

Створимо новий контейнер у файлі docker-compose.yaml.

Це дозволяє не гальмувати основний процес будь-якими довгоживучими завданнями та налагоджувати їх.

start page

Для роботи Celery нам знадобиться база даних Redis.

Встановлення Redis.

Створимо новий контейнер у файлі docker-compose.yaml.

redis-server:
    image: "redis:alpine"

Запуск контейнера.

 docker-compose run redis-server

Увімкнемо його запуск у tmux

 split-window -h \; \
 ...
 select-pane -t 2 \; 
 send-keys 'docker-compose run redis-server' C-m \; \

Установка Celery.

 pip install celery redis

Далі нам необхідно створити програму celery у новому файлі celery_app.py поряд з settings.py.

from celery import Celery
from django.conf import settings
from celery.schedules import crontab
import os

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'prj.settings')


app = Celery('prj')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

Додати імпорт у init.py

 from .celery_app import app as celery_app

У settings.py встановити Redis як брокер повідомлень

REDIS_HOST = os.getenv('SQL_HOST', 'localhost')
REDIS_PORT = os.getenv('SQL_PORT', '6379')

CELERY_BROKER_URL = 'redis://' + REDIS_HOST + ':' + str(REDIS_PORT)

Створимо новий контейнер під чергу завдань celery.

celery-tasks:
    build: .
    restart: always
    working_dir: /app
    command: celery -A prj worker -l info
    volumes:
        - ./prj:/app
    depends_on:
        - redis-server
    env_file:
        - ./.env.dev
    container_name: celery-tasks

Планувальник.

Для того, щоб запускати завдання за заданим розкладом, нам знадобиться запускати окремий процес, який буде класти в чергу завдання за заданим інтервалом часу.

Цей процес називається cellery-beat.

Запускається командою.

celery -A prj beat

Створимо завдання, що виводить поточний час на екран у файлі celery.py

from datetime import datetime

@app.task(bind=True)
def timer_task(self):
    now = datetime.now()
    current_time = now.strftime("%H:%M:%S")
    print(f'Time is: {current_time}')

bind=True - дозволяє звертатися до екземпляра завдання всередині її самої наприклад так self.retry(countdown=5)

Далі створимо планувальник і запустимо завдання з інтервалом 1 хв.

app.conf.beat_schedule = {
  'timer-task': {
    'task': 'prj.celery.timer_task',
    'schedule': crontab(minute='*/1'),
  }
}

Посилання на документацію за інтервалами

Створимо окремий контейнер докер під celery-beat.

celery-beat:
    build: .
    restart: always
    working_dir: /app
    command: celery -A prj beat
    volumes:
        - ./prj:/app
    depends_on:
        - redis-server
    env_file:
        - ./.env.dev
    container_name: celery-beat

Файл для запуску всіх процесів в окремих вікнах tmux.

#!/bin/bash
command -v tmux >/dev/null 2>&1 || { echo >&2 "I require tmux but it's not installed.  Aborting."; exit 1; }

tmux new-session \; \
 split-window -v \; \
 split-window -h \; \
 select-pane -t 0 \; \
 split-window -h \; \
 split-window -h \; \
 send-keys 'docker-compose run db' C-m \; \
 select-pane -t 4 \; \
 send-keys 'docker-compose run django' C-m \; \
 select-pane -t 3 \; \
 send-keys 'docker-compose run redis-server' C-m \; \
 select-pane -t 0 \; \
 send-keys 'docker-compose run celery-tasks' C-m \; \
 select-pane -t 1 \; \
 send-keys 'docker-compose run celery-beat' C-m \; \

Результат.

start page