我使用链式延迟任务和查询游标在app引擎中循环数据。 Python 2.7,使用db(不是ndb)。 E.g。
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版本可能会更改内部实现细节,使依赖于它们的游标无效。如果应用程序尝试使用不再有效的游标,则数据存储区会引发BadRequestError异常。
所以也许发生了什么事,但似乎是一个共同发生的事情,我第一次尝试这种技术时,我发现了内部实施的变化' (除非他们经常发生)。
还有其他解释吗? 有没有办法重新设计我的代码以避免这种情况?
如果没有,我认为唯一的解决方案是标记已处理的资产,然后在查询中添加额外的过滤器以排除这些资产,然后在每次死亡时手动重新启动该过程。
作为参考,this question提出了类似的问题,但接受的答案是使用游标',我已经在做了,所以它不能是同一个问题。
答案 0 :(得分:1)
您可能需要查看AppEngine MapReduce
MapReduce是一种用于处理大量数据的编程模型 以平行和分布的方式。它适用于大型, 长期工作,无法在单一范围内处理 请求,任务如:
- 分析应用程序日志
- 汇总外部来源的相关数据
- 将数据从一种格式转换为另一种格式
- 导出数据以进行外部分析
答案 1 :(得分:0)
当我问这个问题时,我曾经运行过一次代码,并且经历过一次BadRequestError。然后我再次运行它,它完成没有BadRequestError,总共运行了大约6个小时。所以在这一点上我会说最好的解决方案'这个问题是使代码具有幂等性(以便可以重试),然后添加一些代码进行自动重试。
在我的特定情况下,还可以调整查询,以便在光标“到期”的情况下,查询可以在光标停止的情况下重新启动。有效地将查询更改为:
assets = models.Asset.all().order('-size').filter('size <', last_seen_size)
其中last_seen_size
是从每个任务传递到下一个任务的值。