2012-05-23 12 views
3

나는 내 애플 리케이션에 샐러리와 드롭 박스를 결합했으며, 이것으로 드롭 박스가 연결된 사용자는 자신의 사진을 저장할 수있다.작업 내 샐러리 작업

코드 조각을 작성했지만이 코드가 시스템을 죽일 수있는 무한 루프로 이어질 수 있습니다.

내가 탭하는 API는 한 번에 60 장의 사진 만 허용하여 페이지 매김을 제공합니다.

다음은 내 tasks.py 파일의 복사본입니다. 실제로 제대로 작동하지만 올바르게 작동하고 시스템에 너무 많은 영향을 미치지 않는지 확인하고 싶습니다.

class DropboxUsers(PeriodicTask): 
    run_every = timedelta(hours=4) 

    def run(self, **kwargs): 
     logger = self.get_logger(**kwargs) 
     logger.info("Collecting Dropbox users") 

     dropbox_users = UserSocialAuth.objects.filter(provider='dropbox') 
     for db in dropbox_users: 
      ... 
      ... 
      ... 
      sync_images.delay(first, second, third_argument) 
     return True 


@task(ignore_result=True) 
def sync_images(token, secret, username): 
    """docstring for sync_images""" 
    logger = sync_images.get_logger() 
    logger.info("Syncing images for %s" % username) 
    ... 
    ... 
    ... 
    ... 
    feed = api.user_recent_media(user_id='self', count=60) 
    images = feed[0] 
    pagination = feed[1] 
    for obj in images: 
     ### STORE TO DROPBOX 
     ... 
     ... 
     ... 
     response = dropbox.put_file(f, my_picture, overwrite=True) 
    ### CLOSE DB SESSION 
    sess.unlink() 
    if pagination: 
     store_images.delay(first, second, third, fourth_argument) 

@task(ignore_result=True) 
def store_images(token, secret, username, max_id): 
    """docstring for sync_images""" 
    logger = store_images.get_logger() 
    logger.info("Storing images for %s" % username) 
    ... 
    ... 
    ... 
    ... 
    feed = api.user_recent_media(user_id='self', count=60, max_id=max_id) 
    images = feed[0] 
    try: 
     pagination = feed[1] 
    except: 
     pagination = None 
    for obj in images: 
     ### STORE TO DROPBOX 
     ... 
     ... 
     ... 
     response = dropbox.put_file(f, my_picture, overwrite=True) 
    ### CLOSE DB SESSION 
    sess.unlink() 
    if pagination: 
     ### BASICALLY RESTART THE TASK WITH NEW ARGS 
     store_images.delay(first, second, third, fourth_argument) 

    return True 

귀하의 전문성을 높이 평가합니다.

답변

1

큰 문제는 없습니다. 또한 작업이 다른 작업을 시작하는 시스템을 구현했습니다.

잠시 동안 서버를 다시 시작할 때 복제 작업이 샐러리에 문제가있었습니다. 필자는 동일한 인수를 가진 동일한 태스크가 너무 자주 실행되지 않도록 캐싱 백엔드를 사용하는 태스크를 감싸는 데코레이터를 작성했습니다. 무한 루프에 대한 헤지로 유용 할 수 있습니다.

from django.core.cache import cache as _djcache 
from django.utils.functional import wraps 

class cache_task(object): 

    """ Makes sure that a task is only run once over the course of a configurable 
    number of seconds. Useful for tasks that get queued multiple times by accident, 
    or on service restart, etc. Uses django's cache (memcache) to keep track.""" 

    def __init__(self, seconds=120, minutes=0, hours=0): 
     self.cache_timeout_seconds = seconds + 60 * minutes + 60 * 60 * hours 

    def __call__(self, task): 
     task.unsynchronized_run = task.run 
     @wraps(task.unsynchronized_run) 
     def wrapper(*args, **kwargs): 
      key = sha1(str(task.__module__) + str(task.__name__) + str(args) + str(kwargs)).hexdigest() 
      is_cached = _djcache.get(key) 
      if not is_cached: 
       # store the cache BEFORE to cut down on race conditions caused by long tasks 
       if self.cache_timeout_seconds: 
        _djcache.set(key, True, self.cache_timeout_seconds) 
       task.unsynchronized_run(*args, **kwargs) 
     task.run = wrapper 
     return task 

사용법 :

@cache_task(hours=2) 
@task(ignore_result=True) 
def store_images(token, secret, username, max_id): 
    ...