How to send periodic tasks to specific queue in Celery

Periodic tasks are sent to queues by celery beat where you can do everything you do with the Celery API. Here is the list of configurations that comes with celery beat:

https://celery.readthedocs.org/en/latest/userguide/periodic-tasks.html#available-fields

In your case:

CELERYBEAT_SCHEDULE = {
   'installer_recalc_hour': {
        'task': 'stats.installer.tasks.recalc_last_hour',
        'schedule': 15,  # every 15 sec for test
        'options': {'queue' : 'celery_periodic'},  # options are mapped to apply_async options
    },
}

I found solution for this problem:

1) First of all I changed the way for configuring periodic tasks. I used @periodic_task decorator like this:

@periodic_task(run_every=crontab(minute='5'),
               queue='celery_periodic',
               options={'queue': 'celery_periodic'})
def recalc_last_hour():
    dt = datetime.utcnow()
    prev_hour = datetime(dt.year, dt.month, dt.day, dt.hour) \
                - timedelta(hours=1)
    log.debug('Generating task for hour %s', str(prev_hour))
    recalc_hour.delay(prev_hour)

2) I wrote celery_periodic twice in params to @periodic_task:

  • queue='celery_periodic' option is used when you invoke task from code (.delay or .apply_async)

  • options={'queue': 'celery_periodic'} option is used when celery beat invokes it.

I'm sure, the same thing is possible if you'd configure periodic tasks with CELERYBEAT_SCHEDULE variable.

UPD. This solution correct for both DB based and file based storage for CELERYBEAT_SCHEDULER.


And if you are using djcelery Database scheduler, you can specify the queue on the Execution Options -> queue field