在Google App Engine上处理db.Timeout

时间:2009-09-21 18:33:06

标签: python google-app-engine

我正在测试我的应用程序(在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的更好方法是什么?

编辑:

我现在将此用于任何获取查询

""" 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

我有类似的fetch和count函数。

4 个答案:

答案 0 :(得分:7)

这是一个重装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)

答案 1 :(得分:6)

查询偶尔会失败。您可以向用户显示错误消息,也可以重试,如上所述。但是,如果重试,则应该使用thread.sleep在每次重试时添加越来越多的延迟(从50ms开始) - 如果不尽快重试,则重试更有可能成功。

每个请求40个查询是 lot 。您应该考虑重构代码 - 必须能够消除大部分代码!

答案 2 :(得分:2)

看一下这个python Autoretry Datastore Timeouts配方。类似于moraes的回答,但你只需要在初始化时调用一次,而不是装饰执行数据存储操作的函数。

http://appengine-cookbook.appspot.com/recipe/autoretry-datastore-timeouts

答案 3 :(得分:1)

请参阅GAE-Utilities中的新ROTModel。下面的第二个讨论显示了它如何重试。 它是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