在"Background work with the deferred library"文章之后,我创建了一组计划任务来帮助维护我们的应用。它们每个都刷新特定类型的旧实体。
在一种情况下,我们使用类型为key
的非键属性,而不是使用标准的ndb模型DateTimeProperty
属性(用于跟踪已处理的记录)。当我们执行此操作并且我们点击DeadlineExceededError
时,方法的延迟实例在取消deferred.run method中创建的任务参数的过程中死亡。
我们基类中的相关代码:
def _continue(self, start_key, batch_size):
# ...
except DeadlineExceededError:
if self._numBatches > 0:
self.Log("Deferring to a new instance of the process.")
deferred.defer(self._continue, start_key, batchSize)
else:
self.LogWarning("No batches were completely processed. This process will terminate to prevent continuous operation.")
raise deferred.PermanentTaskFailure("DeadlineExceededError occurred before any batches could be completely processed.")
self.Finish()
当方法的延迟副本启动时,会产生此错误:
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 310, in post
self.run_from_request()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 305, in run_from_request
run(self.request.body)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 145, in run
raise PermanentTaskFailure(e)
PermanentTaskFailure: __new__() takes exactly 4 arguments (1 given)
通过pdb
和deferred
库进行更多挖掘(pickle
)会发布更多细节:
1080 def load_newobj(self):
1081 args = self.stack.pop()
1082 cls = self.stack[-1]
1083 -> obj = cls.__new__(cls, *args)
1084 self.stack[-1] = obj
1085 dispatch[NEWOBJ] = load_newobj
和
(Pdb) pp args
()
(Pdb) pp cls
<class 'google.appengine.ext.ndb.query.FilterNode'>
(Pdb) n
TypeError: '__new__() takes exactly 4 arguments (1 given)'
> /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py(1083)load_newobj()
我正在挖掘更多,但现在的基本问题似乎是:
deferred.TaskHandler
的能力的提示(在v.1.6.3 - Feb 28, 2012中引入),这可能有助于解决第一个问题,但找不到任何关于如何执行此操作的示例。答案 0 :(得分:0)
从deferred.py
的来源可以看出,您与@rdodev一起分析得很好,意识到问题是在尝试取消data
参数{ {1}}。这反过来是从run()
调用的,所以这里未被腌制的是请求有效负载本身,它是在您调用run_from_request()
时创建的。
对于deferred.defer()
未被腌制,pickle模块可能需要为其调用构造函数(DateTimeProperty
),但这不可用或者当时提供的方法签名与腌制时的方法签名不同,导致您看到的异常,这些气泡会被捕获并呈现给__new__
。
总的来说,如果您可以生成可靠地重现行为的示例应用程序,那么这可能值得作为缺陷报告发布到public issue tracker。
除此之外,作为现在的解决方法,我使用了不会导致错误的内容,例如PermanentTaskFailure
的字符串表示形式或常规{{ 1}}对象,甚至是另一个DateTimeProperty
类,它不会引起问题。您也可以尝试使用taskqueue library本身,它非常易于使用,并且不应与您当前的用例有很大的不同。