Задания Celery не выполняются на heroku (приложение python/django)
У меня есть приложение Django с некоторыми запланированными задачами. Приложение развернуто на Heroku с Redis. Задание выполняется, если его вызвать синхронно в консоли или локально, когда у меня также запущены redis и celery. Однако запланированные задания не выполняются на Heroku.
Моя задача:
@shared_task(name="send_emails")
def send_emails():
.....
celery.py:
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from celery.schedules import crontab
# set the default Django settings module for the 'celery' program.
# this is also used in manage.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.settings')
# Get the base REDIS URL, default to redis' default
BASE_REDIS_URL = os.environ.get('REDIS_URL', 'redis://localhost:6379')
app = Celery('my_app')
# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
app.conf.broker_url = BASE_REDIS_URL
# this allows you to schedule items in the Django admin.
app.conf.beat_scheduler = 'django_celery_beat.schedulers.DatabaseScheduler'
# These are the scheduled jobs
app.conf.beat_schedule = {
'send_emails_crontab': {
'task': 'send_emails',
'schedule': crontab(hour=9, minute=0),
'args': (),
}
}
В Procfile:
worker: celery -A my_app worker --beat -S django -l info
Я запустил рабочего с помощью heroku ps:scale worker=1 -a my-app.
Я могу видеть зарегистрированные задачи под [tasks] в журналах рабочего.
Однако запланированные задачи не выполняются в назначенное время. Вызов send_emails.delay() в производственной консоли работает.
Как заставить рабочего остаться в живых и/или запустить задание в запланированное время?
У меня есть обходной путь с использованием команды и планировщика heroku. Просто не уверен, что это лучший способ сделать это.
Если вы находитесь на бесплатном демо, вы должны знать, что сервер heroku спит, и если ваша запланированная задача будет выполнена, когда сервер спит, она не будет запущена.
Делюсь с вами любыми идеями.
Запустите консоль и получите время даты Dyno. Dyno использует локальное время США.
DynoFree спит каждые 30 минут и только 450 часов в месяц.
Попробуйте заменить сельдерей на BackgroundScheduler, вам нужно добавить скрипт clock.py как:
from myapp import myfunction from datetime import datetime from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.blocking import BlockingScheduler from time import monotonic, sleep, ctime import os sched = BlockingScheduler() hour = int(os.environ.get("SEARCH_HOUR")) minutes = int(os.environ.get("SEARCH_MINUTES")) @sched.scheduled_job('cron', day_of_week='mon-sun', hour=hour, minute = minutes) def scheduled_job(): print('This job: Execute myfunction every at ', hour, ':', minutes) #My function myfunction() sched.start(
)
В Procfile:
clock: python clock.py
и запустить:
heroku ps:scale clock=1 --app thenameapp
Приветствуется.