芹菜击败 - 每个任务的不同时区

时间:2014-02-17 11:02:07

标签: python django django-celery celerybeat

我正在使用芹菜来安排一些任务。我可以使用CELERY_TIMEZONE设置来使用crontab计划安排任务,并在上述时区的预定时间运行。

但我希望能够在同一个应用程序中为不同的时区设置多个此类任务(单个django settings.py)。我知道在安排任务时需要在哪个时区运行哪个任务。

是否可以为每个任务指定不同的时区?

我正在使用django(1.4)和芹菜(3.0.11)以及django芹菜(3.0.11)。

我查看了djcelery.schedulers.DatabaseScheduler类及其基类,但我无法弄清楚时区的使用方式和位置。我可以编写一个自定义调度程序,使每个作业可以在不同的时区运行吗?

谢谢,

4 个答案:

答案 0 :(得分:10)

您可以在芹菜计划中实现单个任务的时区感知计划。这样,您可以通过为每个芹菜时间表指定一个单独的现在功能,根据特定时区的当地时间(也可以调整为夏令时)来运行任务

crontab支持nowfun argument指定用于检查是否应该运行的日期时间函数

import datetime
import pytz
nowfun = lambda: datetime.datetime.now(pytz.timezone('Europe/Berlin'))

在您的日程安排中,通过

将此功能设置为日期时间功能
'periodic_task': {
    'task': 'api.tasks.periodic',
    'schedule': crontab(hour=6, minute=30, nowfun=nowfun)
}

每天早上6点30分CET调整为夏令时。

如果您多次使用该功能,请考虑创建帮助

from functools import partial
cet_crontab = partial(crontab, nowfun=nowfun)
'periodic_task': {
    'task': 'api.tasks.periodic',
    'schedule': cet_crontab(hour=6, minute=30)
}

确保您设置了CELERY_ENABLE_UTC = False,否则芹菜会将您的日程安排转换为UTC。

答案 1 :(得分:1)

我认为最简单的方法是使用装饰器mock

from mock import patch

@task
@patch.multiple(settings, CELERY_TIMEZONE='time_zone')
def my_task(*args):
    #do your staff

我还没有测试过,但似乎没错。我希望我能帮到你:)。

答案 2 :(得分:0)

也许我误解了这个问题,但是如果你想在不同时区的某个时间运行任务,你能不能只按时区之间的小时差来调整预定时间?例如,如果我希望任务在下午5点在两个不同的TZ中运行:

# settings.py
CELERY_TIMEZONE = "US/Eastern"

CELERYBEAT_SCHEDULE = { 
    # Task to run in EST
    'schedule-my-est-task': {
        'task': 'path.to.my.est.task',
        'schedule': crontab(minute=0, hour=17),
    },
    # Task to run in UTC - hour time is offset
    'schedule-my-utc-task': {
        'task': 'path.to.my.utc.task',
        'schedule': crontab(minute=0, hour=10), 
    },
}

答案 3 :(得分:0)

就我而言,我需要一个函数,该函数每次都会运行,并从db中获取特定值的时区。
我创建了一个新函数,该函数将接受一个变量并为我提供所需的时区。


def get_time(db_query: str) -> datetime.datetime:
    """Extract timezone from DB"""

    # get location from db
    timezone = 'get timezone for location'
    # return calculated datetime using timezone
    return datetime.datetime.now(pytz.timezone(timezone))


def custom_crontab(*args, **kwargs):
    """Create a custom crontab that will call get_time function and assign value to nowfun"""

    db_query = kwargs.pop("db_query")
    nowfun = get_time(db_query)
    kwargs['nowfun'] = nowfun
    # return the call to crontab
    return crontab(*args, **kwargs)


beat_schedule = {
    'periodic_task': {
        'task': 'main_job',
        'schedule': custom_crontab(minute=0, db_query='some_value'),
    }
}