修正datastore_cache无效的bug
2010 3 19 03:11 PM 2174次查看
分类:Google App Engine 标签:Google App Engine, Python
这个bug解释起来非常麻烦,我也不清楚是不是Google更改了实现而导致的,先把API调用机制介绍一下吧。
在调用GAE的API时,app会根据服务名(例如'datastore_v3'、'memcache'等)来从一个stub_map(存根表)里获取API代理。接着将request和respone(都是PB对象)传给这个API代理,并根据不同的call名,发出相应的异步RPC。
可惜的是Google并不将异步API开放出来,到现在也只有异步urlfetch的开放API,所以要用的话,只能自己看代码了。这个异步RFC调用后,就执行了一个wait函数(于是变成了同步RFC),等待RFC返回,然后检查respone并返回。
而datastore_cache就是修改了这个存根表,将datastore_v3这个服务拦截了,加入了一层memcache。可虽然拦截了存根表,RPC的构造函数参数却忘记修改了,于是仍然是传原来的对象。
解决的办法很简单,自己写个CreateRPC即可。
先在模块头加上这行:
from google.appengine.api import apiproxy_rpc
然后在APIProxyShim类里加上这个方法: def CreateRPC(self):
return apiproxy_rpc.RPC(stub=self)
于是问题解决。顺带一提,作者写的文档貌似有问题。实际上DatastoreCachingShim实现了_Dynamic_Get,而没覆盖_Dynamic_RunQuery,所以对查询是无效的,和文档所说正好相反。
所以我也写了个实现:
def _Dynamic_RunQuery(self, query, query_result):
"""Intercepts query results and caches the returned entities."""
if query.has_transaction():
self.CallWrappedStub('RunQuery', query, query_result)
return
key = 'RunQuery:' + query.Encode()
results = memcache.get(key)
if results is None:
self.CallWrappedStub('RunQuery', query, query_result)
memcache.set(key, query_result, 600)
else:
query_result.MergeFrom(results)
有需要的可以去这里下载修改后的源码。
0条评论 你不来一发么↓