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()
Пожалуйста, поправьте меня, если я где-то ошибаюсь.