Запускать функцию, когда очередь задач пуста в appengine

#python #google-app-engine #cron #task-queue

#python #google-app-engine #cron #очередь задач

Вопрос:

У меня каждый день есть задание cron для выполнения вызова API и извлечения некоторых данных. Для каждой строки данных я запускаю очередь задач для обработки данных (что включает в себя поиск данных через дополнительные API). Как только все это закончится, мои данные не изменятся в течение следующих 24 часов, поэтому я кэширую их.

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

В настоящее время я делаю это действительно беспорядочно, просто планируя два задания cron, подобные этому:

 class fetchdata(webapp.RequestHandler):
def get(self):
    todaykey = str(date.today())
    memcache.delete(todaykey)
    topsyurl = 'http://otter.topsy.com/search.json?q=site:open.spotify.com/albumamp;window=damp;perpage=20'
    f = urllib.urlopen(topsyurl)
    response = f.read()
    f.close()

    d = simplejson.loads(response)
    albums = d['response']['list']
    for album in albums:
        taskqueue.add(url='/spotifyapi/', params={'url':album['url'], 'score':album['score']})

class flushcache(webapp.RequestHandler):
    def get(self):
        todaykey = str(date.today())
        memcache.delete(todaykey)   
  

Затем мой cron.yaml выглядит следующим образом:

 - description: gettopsy
  url: /fetchdata/
  schedule: every day 01:00
  timezone: Europe/London

- description: flushcache
  url: /flushcache/
  schedule: every day 01:05
  timezone: Europe/London
  

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

Есть ли лучший способ кодирования этого? Похоже, мое решение не самое лучшее….

Спасибо, Том

Ответ №1:

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

Комментарии:

1. спасибо, ник — приятно знать, что я не пропустил ничего очевидного. Я попробую то, что вы предлагаете

Ответ №2:

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

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

время ожидания — это таймер, который постоянно сбрасывается каким-либо процессом. когда этот процесс завершается, таймер не сбрасывается и в конечном итоге истекает. итак, у меня были все различные задачи, которые составляли часть моего сложного фонового процесса, сбросили таймер, и вместо проверки, когда очередь была пуста, у меня было задание cron, которое проверяло, когда истек таймер.

конечно, чтобы это было эффективно, таймер должен избегать постоянной записи в хранилище данных. код в http://acooke.org/cute/Deadmantim0.html позволяет избежать этого, слегка смягчая поведение и используя memcache для хранения копии объекта timer и сброса его в хранилище только по истечении значительного промежутка времени.

ps это более эффективно, чем то, что вы описываете, потому что для этого не нужно так часто записывать данные в базу данных. это также более надежно, потому что вам не нужно точно отслеживать, что происходит.

Комментарии:

1. И это также менее надежно, поскольку счетчик может истечь из-за того, что все выполняемые задачи выполняются слишком медленно. Я думаю, на практике это может быть достаточно маловероятно.