django celery: как программно установить задачу на определенный интервал - PullRequest
6 голосов
/ 24 августа 2011

Я обнаружил, что могу настроить запуск задачи с определенным интервалом в определенное время, начиная с здесь , но это было сделано только во время объявления задачи.Как установить задачу для периодического динамического запуска?

Ответы [ 4 ]

8 голосов
/ 24 августа 2011

Расписание получено из настройки и, таким образом, кажется неизменным во время выполнения.

Вы, вероятно, можете выполнить то, что ищете, используя ETA задания .Это гарантирует, что ваша задача не будет запущена до требуемого времени, но не обещает запустить задачу в назначенное время - если рабочие будут перегружены в назначенное ETA, задача может быть запущена позже.

Если это ограничение не является проблемой, вы можете написать задачу, которая сначала запустится сама, например:

@task
def mytask():
    keep_running = # Boolean, should the task keep running?
    if keep_running:
        run_again = # calculate when to run again
        mytask.apply_async(eta=run_again)
    # ... do the stuff you came here to do ...

Основным недостатком этого подхода является то, что вы полагаетесь на хранилище задачзапомнить задачи в полете.Если один из них завершится неудачей, прежде чем запустить следующий, задание больше никогда не запустится.Если ваш брокер не был сохранен на диске и умирает (принимая с собой все выполняемые в полете задачи), то ни одна из этих задач не запустится снова.

Вы можете решить эти проблемы с помощью некоторого рода регистрации транзакций ипериодическая задача «няни», работа которой состоит в том, чтобы найти такие повторяющиеся задачи, которые умерли безвременной смертью и оживить их.

Если бы мне пришлось реализовать то, что вы описали, я думаю, что именно так я бы к этому подошел.

2 голосов
/ 24 августа 2011

celery.task.base.PeriodicTask определяет is_due, который определяет, когда должен быть следующий запуск. Вы можете переопределить эту функцию, чтобы она содержала вашу собственную динамическую логику работы. Смотрите документы здесь: http://docs.celeryproject.org/en/latest/reference/celery.task.base.html?highlight=is_due#celery.task.base.PeriodicTask.is_due

Пример:

import random
from celery.task import PeriodicTask

class MyTask(PeriodicTask):

    def run(self, **kwargs):
        logger = self.get_logger(**kwargs)
        logger.info("Running my task")

    def is_due(self, last_run_at):
        # Add your logic for when to run. Mine is random
        if random.random() < 0.5:
            # Run now and ask again in a minute
            return (True, 60)
        else:
            # Don't run now but run in 10 secs
            return (True, 10)
0 голосов
/ 24 мая 2014

Это должно помочь вам ... http://celery.readthedocs.org/en/latest/faq.html#can-i-change-the-interval-of-a-periodic-task-at-runtime

После того, как вы определили свое расписание, назначьте его для своей задачи, как предложено в asksol.

CELERYBEAT_SCHEDULE = {    
    "my_name": {
        "task": "myapp.tasks.task",
        "schedule": myschedule(),    
    }
}

Выможет также потребоваться изменить CELERYBEAT_MAX_LOOP_INTERVAL, если вы хотите, чтобы расписание обновлялось чаще, чем каждые пять минут.

0 голосов
/ 24 августа 2011

см. Здесь http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

я думаю, что вы не можете сделать это динамически ... лучший способ - создать задачу в задаче: D

например, вы хотите запустить что-то за X сек.позже вы создаете новое задание с задержкой х секунд и в этом задании создаете еще одно задание с задержкой N * х секунд ...

...