Search code examples
pythondjangocroncelerycelerybeat

Celery Beat scheduler won't execute my task in Django


I have had some trouble setting up my celery module in Django. Not only am I very confused by the settings requirement, I also have a hard time understanding my errors.

I want to run a function at a specific time everyday, something I used to do with crontab. Celery is apparently better suited for this type of tasks, that's why I'm trying to move towards this solution.

The set up seems to be okay and I see the celery scheduler run when I invoke it but my task is not processed when the interval kicks in.

I saw a lot (!!!) of different set-up for celery so my code might incorporate redundancies and unnecessary lines.

The function I want to trigger is called team_accountabillity() and is present in my app "myteam.task.py"

I have Celery 4.4.0 and I use rabbitMQ as a queue manager (I have also installed redis because many tutorials went with this one).

Here is my proj/settings.py

from __future__ import absolute_import
import os
from datetime import timedelta
from celery import Celery
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')


CELERY_BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_BEAT_SCHEDULER = {
                        'team accountability': {
                        'task':'team_accountability', 'schedule': timedelta(seconds=10),
                        },
                    }
CELERY_TIMEZONE = 'UTC'
CELERY_ENABLE_UTC = True

INSTALLED_APPS = [
    'celerybeat_status',
    'django_celery_beat',
    'myteam.apps.MyteamConfig',
]

The proj/celery.py file:

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from celery.schedules import crontab
from django.apps import apps
from django.conf import settings

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
app = Celery('proj')


app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks(lambda: [n.name for n in apps.get_app_configs()])

##documentation regarding the next line:
##https://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#beat-entries
##I find it very weird that this command is very similar to the CELERY_BEAT_SCHEDULER in settings.py
##I honestly don't know what this does
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    sender.add_periodic_task(10.0, team_accountability, name='team accountability')

@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

The proj/init.py file:

from __future__ import absolute_import, unicode_literals

from .celery import app as celery_app
__all__ = ('celery_app')

And finally, here is my app/task.py (myteam/task.py)

from __future__ import absolute_import, unicode_literals

from celery import shared_task
from myteam.models import Team


##decorator should be @shared_task or @task???
@shared_task
def team_accountability():
    t_all = Team.objects.all()
    for t in t_all:
        total = 0
        s_all = t.stocks.all()
        for s in s_all:
            symbol = s.symbol
            queryset = Stock.objects.filter(symbol__contains=symbol).order_by("-id").first()
            total = total + queryset.change_percent
        t.total = round(total, 3)
        t.save()

With all this being said, here is what I get in when I run the command:

celery -A proj worker -l debug

What I get is this:

[2020-02-21 12:39:03,420: DEBUG/MainProcess] | Worker: Preparing bootsteps.
[2020-02-21 12:39:03,420: DEBUG/MainProcess] | Worker: Building graph...
[2020-02-21 12:39:03,421: DEBUG/MainProcess] | Worker: New boot order: {StateDB, Beat, Timer, Hub, Pool, Autoscaler, Consumer}
[2020-02-21 12:39:03,429: DEBUG/MainProcess] | Consumer: Preparing bootsteps.
[2020-02-21 12:39:03,429: DEBUG/MainProcess] | Consumer: Building graph...
[2020-02-21 12:39:03,447: DEBUG/MainProcess] | Consumer: New boot order: {Connection, Events, Mingle, Gossip, Tasks, Control, Agent, Heart, event loop}

 -------------- celery@matador-B450M-DS3H v4.4.0 (cliffs)
--- ***** ----- 
-- ******* ---- Linux-4.15.0-70-generic-x86_64-with-debian-buster-sid 2020-02-21 12:39:03
- *** --- * --- 
- ** ---------- [config]
- ** ---------- .> app:         TheRodeoProject:0x7f00682ecc10
- ** ---------- .> transport:   redis://localhost:6379//
- ** ---------- .> results:     redis://localhost:6379/
- *** --- * --- .> concurrency: 12 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery


[tasks]
  . TheRodeoProject.celery.debug_task
  . celery.accumulate
  . celery.backend_cleanup
  . celery.chain
  . celery.chord
  . celery.chord_unlock
  . celery.chunks
  . celery.group
  . celery.map
  . celery.starmap

[2020-02-21 12:39:03,455: DEBUG/MainProcess] | Worker: Starting Hub
[2020-02-21 12:39:03,455: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:03,455: DEBUG/MainProcess] | Worker: Starting Pool
[2020-02-21 12:39:03,891: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:03,891: DEBUG/MainProcess] | Worker: Starting Consumer
[2020-02-21 12:39:03,891: DEBUG/MainProcess] | Consumer: Starting Connection
[2020-02-21 12:39:03,900: INFO/MainProcess] Connected to redis://localhost:6379//
[2020-02-21 12:39:03,901: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:03,901: DEBUG/MainProcess] | Consumer: Starting Events
[2020-02-21 12:39:03,908: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:03,908: DEBUG/MainProcess] | Consumer: Starting Mingle
[2020-02-21 12:39:03,908: INFO/MainProcess] mingle: searching for neighbors
[2020-02-21 12:39:04,924: INFO/MainProcess] mingle: all alone
[2020-02-21 12:39:04,924: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:04,925: DEBUG/MainProcess] | Consumer: Starting Gossip
[2020-02-21 12:39:04,930: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:04,930: DEBUG/MainProcess] | Consumer: Starting Tasks
[2020-02-21 12:39:04,934: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:04,934: DEBUG/MainProcess] | Consumer: Starting Control
[2020-02-21 12:39:04,935: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:04,935: DEBUG/MainProcess] | Consumer: Starting Heart
[2020-02-21 12:39:04,936: DEBUG/MainProcess] ^-- substep ok
[2020-02-21 12:39:04,936: DEBUG/MainProcess] | Consumer: Starting event loop
[2020-02-21 12:39:04,937: DEBUG/MainProcess] | Worker: Hub.register Pool...
[2020-02-21 12:39:04,937: WARNING/MainProcess] /home/matador/anaconda3/envs/venv1/lib/python3.7/site-packages/celery/fixups/django.py:203: UserWarning: Using settings.DEBUG leads to a memory
            leak, never use this setting in production environments!
  leak, never use this setting in production environments!''')
[2020-02-21 12:39:04,937: INFO/MainProcess] celery@matador-B450M-DS3H ready.

As you can see the task I wanted to add to my queue does not appear when I run this command. The rest seems to be doing ok.

EDIT:

It seems the solution to this problem is to use celery beat instead of the regular celery.


Solution

  • You likely need to run a worker celery process.

    celery -A proj worker -l debug