Celery beat sends scheduled task only once and then doesn't send task when restarted

I am using Celery beat to perform a task that is supposed to be executed at on specific time. I was trying to excute it now by changing the time just to see if it works correctly. What I have noticed is it sends the task correctly when I run a fresh command that is celery -A jgs beat -l INFO but then suppose I change the time in the schedule section from two minutes or three minutes from now and then again run the above command, beat does not send the task. Then I noticed something strange. If I go to the admin area and delete all the other old tasks that were created in the crontab table, and then run the command again it sends the task again to the worker.

The tasks are being traced by the worker correctly and also the celery worker is working correctly. Below are the codes that I wrote to perform the task.

celery.py

from __future__ import absolute_import, unicode_literals

import os

from celery import Celery

from django.conf import settings

from celery.schedules import crontab

from django.utils import timezone

from datetime import timezone


# Set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'jgs.settings')

app = Celery('jgs')

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.

app.conf.enable_utc = False

app.conf.update(timezone = 'Asia/Kolkata')

# app.conf.update(BROKER_URL=os.environ['REDIS_URL'],
#                 CELERY_RESULT_BACKEND=os.environ['REDIS_URL'])

app.config_from_object('django.conf:settings', namespace='CELERY')


# Celery beat settings 

app.conf.beat_schedule = {
    'send-expiry-email-everyday': {
        'task': 'control.tasks.send_expiry_mail',
        'schedule': crontab(hour=1, minute=5),
    } 
}

# Load task modules from all registered Django apps.
app.autodiscover_tasks()


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

control/tasks.py

from celery import shared_task


from django.core.mail import message, send_mail, EmailMessage
from django.conf import settings
from django.template.loader import render_to_string

from datetime import datetime, timedelta


from account.models import CustomUser

from home.models import Contract

@shared_task
def send_expiry_mail():

    template = render_to_string('expiry_email.html')
    email = EmailMessage(
        'Registration Successfull',                                   #subject
        template,                                                      # body
        settings.EMAIL_HOST_USER,
        ['emaiid@gmail.com'],                                       # sender email
    )
    email.fail_silently = False
    email.content_subtype = 'html'       # WITHOUT THIS THE HTML WILL GET RENDERED AS PLAIN TEXT
    email.send()
    return "Done"

settings.py

############# CELERY SETTINGS #######################

CELERY_BROKER_URL = 'redis://127.0.0.1:6379'
# CELERY_BROKER_URL = os.environ['REDIS_URL']
CELERY_ACCEPT_CONTENT =['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Kolkata'
CELERY_RESULT_BACKEND = 'django-db'

# CELERY BEAT CONFIGURATIONS

CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

commands that I am using for worker

celery -A jgs.celery worker --pool=solo -l info

for beat

celery -A jgs beat -l INFO

Please correct me where I going wrong or what I am writing wrong, I completely in beginer phase in this async part.

I am really sorry if my sentences were confusing above.

Back to Top