2011-08-24 4 views
5

here에서 특정 시간에 특정 간격으로 실행되도록 태스크를 설정할 수 있다는 것을 알았지 만 태스크 선언 중에 만 수행되었습니다. 태스크를 주기적으로 동적으로 실행하도록 설정하려면 어떻게합니까? 당신은 당신이 새로운 만들 나중에 X의 초 동안 뭔가를 실행하려는 예를 들어 Ddjango celery : 특정 간격으로 프로그래밍 방식으로 실행되도록 태스크를 설정하는 방법

:

답변

7

일정은 derived from a setting이며, 따라서 런타임시 변경 불가능한 것으로 보입니다.

아마도 Task ETAs을 사용하여 찾고있는 것을 달성 할 수 있습니다. 이렇게하면 전에 원하는 시간을 실행하지 않지만 지정된 시간에 작업을 실행할 것을 약속하지 않습니다. 작업자가 지정된 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 ... 

이 방법의 가장 큰 단점은 당신이 작업을 기억해야 할 taskstore에 의존하고 있다는 점이다를 비행 중. 그 중 하나가 다음 발사 전에 발사되지 않으면 작업이 다시 실행되지 않습니다. 브로커가 디스크에 저장되지 않고 죽는 경우 (실행중인 모든 작업을 수행) 해당 작업은 다시 실행되지 않습니다.

일종의 트랜잭션 로깅과 불규칙한 사망으로 사망 한 반복 작업을 찾아주기 위해주기적인 "유모"작업으로 이러한 문제를 해결할 수 있습니다.

설명해 주신 내용을 구현해야한다면이 방법을 사용하는 것이 좋습니다.

+3

그렇습니다. 스케줄러는 동적 스케줄에 최적화되어 있지 않지만 위에서 설명한대로 is_due 메소드를 사용하여 자신의 '스케줄'을 구현할 수 있습니다. 또한 스케줄 재조정 자체는 많은 옵션이지만 많은 작업을 필요로합니다. 첫 번째 작업이 항상 실행되도록하십시오. 그리 쉽지는 않습니다. 또 다른 옵션은 Django-Celery에서 DatabaseScheduler를 사용하는 것입니다. 이것은 Dynamic 스케쥴을 지원하고 Django 프로젝트 외부에서도 사용할 수 있습니다. 또한, 자신의 스케줄러를 만드는 것이 그리 어렵지 않습니다. – asksol

+0

@asksol, django-celery의 문서는 비어 있습니다.databaseScheduler를 사용하는 방법은 어디서 찾을 수 있습니까? – goh

+1

@amateur 글쎄, 문서는 실제로 부족하다 : – asksol

1

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

내가 런타임 중에 오버라이드하는 방법의 예를 들어 줄 수 있습니까? 나는 periodicTask 클래스를위한 run()이 없기 때문에 .delay를 사용할 수 없다고 생각한다. – goh

+0

커스텀 is_due 메소드로 자신의 스케쥴 클래스 (celery.schedules.schedule)를 정의한다. 'CELERYBEAT_SCHEDULE = { "my name": { "task": "myapp.mytask", 일정 ": myschedule()}}' – asksol

0

일부 ... 사용자 지정 일정을 정의하면 asksol는이 같은 http://celery.readthedocs.org/en/latest/faq.html#can-i-change-the-interval-of-a-periodic-task-at-runtime

, 당신의 작업에 할당 위에 제안했다. 당신이 당신의 일정이 더 자주 매 5 분 이상 업데이트 할 경우

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

는 또한 CELERYBEAT_MAX_LOOP_INTERVAL을 수정할 수 있습니다.

관련 문제