【发布时间】:2016-02-24 05:44:10
【问题描述】:
我正在使用链式延迟任务和查询游标在应用引擎中循环数据。 Python 2.7,使用 db(不是 ndb)。例如
def loop_assets(cursor = None):
try:
assets = models.Asset.all().order('-size')
if cursor:
assets.with_cursor(cursor)
for asset in assets.run():
if asset.is_special():
asset.yay = True
asset.put()
except db.Timeout:
cursor = assets.cursor()
deferred.defer(loop_assets, cursor = cursor, _countdown = 3, _target = version, _retry_options = dont_retry)
return
这总共运行了大约 75 分钟(每个任务大约 1 分钟),然后引发了这个异常:
BadRequestError: The requested query has expired. Please restart it with the last cursor to read more results.
阅读the docs,唯一声明的原因是:
新的 App Engine 版本可能会更改内部实现细节,使依赖它们的游标失效。如果应用程序尝试使用不再有效的游标,Datastore 会引发 BadRequestError 异常。
所以也许这就是发生的事情,但似乎巧合的是,我第一次尝试这种技术时遇到了“内部实现的变化”(除非它们经常发生)。
对此还有其他解释吗? 有没有办法重新设计我的代码以避免这种情况?
如果没有,我认为唯一的解决方案是标记哪些资产已被处理,然后在查询中添加一个额外的过滤器以排除这些资产,然后在每次进程终止时手动重新启动进程。
作为参考,this question 提出了类似的问题,但接受的答案是“使用光标”,我已经在这样做了,所以这不可能是同一个问题。
【问题讨论】:
-
值得注意的是,BadRequestError 并不总是导致实现更改的原因——它可能是由单个子查询超时引起的。实施重试可能是一种解决方案。
-
@Adam 谢谢。您是否有指向有关 BadRequestError 其他原因的任何文档的链接? - 很想读一读。
标签: python google-app-engine google-cloud-datastore