Работа с db.Timeout в Google App Engine - PullRequest
       20

Работа с db.Timeout в Google App Engine

4 голосов
/ 21 сентября 2009

Я тестирую свое приложение (на Google App Engine живых серверах) и, как я его написал, в моем коде около 40 операторов db.GqlQuery () (в основном часть классов) .

Я продолжаю получать db.Timeout очень часто хотя.

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

  querySucceeded = False
  while not querySucceeded :
    try :
      result = db.GqlQuery( """xxx""" ).get()
      querySucceeded = True #only get here if above line doesn't raise exc
    except :
      querySucceeded = False

Это нормально? Ты согласен? Какой лучший способ борьбы с db.Timeouts?

Edit:

Теперь я использую это для любых запросов get

""" Query gets single result """
def queryGet( gql ) :
  querySucceeded = False
  while not querySucceeded :
    try :
      result = db.GqlQuery( gql ).get()
      querySucceeded = True #only get here if above line doesn't raise
    except :
      querySucceeded = False

  return result

У меня есть похожие функции для выборки и подсчета.

Ответы [ 4 ]

7 голосов
/ 14 ноября 2009

Вот декоратор для повторной попытки на db.Timeout, адаптированный от одного из фреймворка Kay:

import logging, time
from google.appengine.ext import db

def retry_on_timeout(retries=3, interval=1.0, exponent=2.0):
    """A decorator to retry a given function performing db operations."""
    def _decorator(func):
        def _wrapper(*args, **kwargs):
            count = 0
            while True:
                try:
                    return func(*args, **kwargs)
                except db.Timeout, e:
                    logging.debug(e)
                    if count >= retries:
                        raise e
                    else:
                        sleep_time = (exponent ** count) * interval
                        logging.warning("Retrying function %r in %d secs" %
                            (func, sleep_time))
                        time.sleep(sleep_time)
                        count += 1

        return _wrapper

    return _decorator

Чтобы использовать его, просто украсьте любую функцию, которая выполняет операции с БД, и вы хотите повторить попытку:

@retry_on_timeout()
def do_the_stuff(models):
    return db.put(models)
6 голосов
/ 22 сентября 2009

Запросы будут иногда терпеть неудачу. Вы можете либо показать сообщение об ошибке пользователю, либо повторить попытку, как вы делали выше. Однако, если вы повторите попытку, вы должны использовать thread.sleep, чтобы добавить увеличивающуюся задержку (начиная, скажем, с 50 мс) к каждой повторной попытке - повторные попытки с большей вероятностью будут успешными, если они не будут повторяться как можно быстрее.

40 запросов на запрос - это лот . Вы должны рассмотреть возможность рефакторинга вашего кода - должно быть возможно устранить большинство из них!

2 голосов
/ 25 декабря 2009

Взгляните на этот рецепт тайм-аутов Autoretry Datastore. Подобно ответу Мораса, но вам нужно вызывать его только один раз во время инициализации, а не украшать функции, выполняющие операции с хранилищем данных.

http://appengine -cookbook.appspot.com / рецепт / autoretry-Datastore-таймауты

1 голос
/ 25 сентября 2009

См. Новую ROTModel в GAE-Utilities. Второе обсуждение ниже показывает, как это повторяется. Это подкласс db.Model, поэтому ваши классы могут наследовать от ROTModel и использовать его повторные попытки.

http://code.google.com/p/gaeutilities

http://groups.google.com/group/google-appengine/browse_thread/thread/ac51cc32196d62f8/aa6ccd47f217cb9a?lnk=gst&q=timeout#aa6ccd47f217cb9a

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...