Celery beat не отправляет задание на worker в heroku, сконфигурированный в одном dyno на бесплатном уровне

Я делаю сайт, где пользователь должен принять соглашение, а затем для него устанавливается дата истечения срока действия. В эту дату договор должен быть просрочен путем установки булевого поля contract_expired в True и отправки электронного письма соответствующему пользователю об этом. Я использовал для этого celery beat. Поскольку сайт находится на стадии тестирования, он размещен на бесплатном уровне dyno в heroku, поэтому мне пришлось настроить один dyno для web, а другой для celery worker и beat. Я запланировал задачу для beat, которая будет запускаться ежедневно в 9 утра, чтобы проверить экзипири для пользователей, а затем выполнить работу, как указано выше. Эта функция работала правильно, когда я тестировал ее на localhost, т.е. запустив два отдельных терминала для worker и beat. Но сегодня в 9 утра она не запустилась в heroku. Ниже приведены коды, которые я написал для всего процесса

procfile

release: python manage.py migrate
web: gunicorn jgs.wsgi --log-file -
celeryworker: celery -A jgs.celery worker & celery -A jgs beat -l INFO & wait -n

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=9, minute=0)
    } 
}

# Load task modules from all registered Django apps.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


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

settings.py

#################  REDIS SETTINGS ######################

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": os.environ.get('REDIS_URL'),
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}


############# 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'

и задание, которое должно быть запланировано в tasks.py

@shared_task(bind=True)
def send_expiry_mail(self):

    
     
        users = Contract.objects.all().filter(date_of_expiration__contains = datetime.today().date())

        for user in users:

            # print('\n users', user.user,' and their expiry status is ', user.contract_expired)

            user.contract_expired = True

            user.save()

            # print('\n users after expiring ', user.user,' and their expiry status is now changed to ', user.contract_expired, ' and saved')

            to_email = user.user.email 

            name = user.user.full_name 

            # print('\n sending mail to ', to_email)      

            template = render_to_string('expiry_email.html',{'name':name,})
            email = EmailMessage(
                'Contract Expiration',                                   #subject
                template,                                                      # body
                settings.EMAIL_HOST_USER,
                [to_email],                                       # sender email
            )
            email.fail_silently = False
            email.content_subtype = 'html'       # WITHOUT THIS THE HTML WILL GET RENDERED AS PLAIN TEXT
            email.send()

This shows that the task is scheduled in db crontab table

peiodic task table in db

running process in heroku

Пожалуйста, поправьте меня, если я где-то ошибаюсь.

Вернуться на верх