NDB异步API和get_or_insert_async

时间:2012-02-29 18:54:17

标签: python google-app-engine app-engine-ndb

我正试图绕过异步api,但没有取得多大成功。

我在实验室项目中的设置相当简单。我的模型看起来像这样:

class SearchIndex(model.Model):
    name = model.StringProperty(required=True)
    reference_list = model.KeyProperty(repeated=True)

使用get_or_insert并检查reference_list是否包含密钥的方法,如果不添加它。实体下面是模型实体,列表是字符串列表[“abc”,“def”,“ghi”]

@classmethod
    def store_list_in_index(cls, list, entity):
        put_queue = []

        for verb in list:
            index_entity = cls._SEARCH_INDEX_DB_MODEL.get_or_insert(verb, name=verb)
            if not entity.key in index_entity.reference_list:
                index_entity.reference_list.append(entity.key)
                put_queue.append(index_entity)

        if put_queue:
            ndb.put_multi_async(put_queue)

这可以按照我想要的方式工作,但是时间很长。如果列表大约是20-30倍。花了大约15-20秒。

所以我开始看看async api。但是不要走得太远。现在它不会在db中存储任何东西:

@classmethod
def store_list_in_index(cls, list, entity):
    put_queue = []
    async_queue = []

    @tasklets.tasklet
    def txn(verb, entity):
        ent = yield cls._SEARCH_INDEX_DB_MODEL.get_or_insert_async(verb, name=verb)
        if not entity.key in ent.reference_list:
            ent.reference_list.append(entity.key)
            put_queue.append(ent)
        raise tasklets.Return(ent)

    for verb in list:
        en = txn(verb, entity)

    if put_queue:
        ndb.put_multi_async(put_queue)

我真的不明白在哪里,因为我不了解tasklets和yield的概念。任何人都有任何想法或能指出我的方向吗?

修改

我最终得到了这个解决方案:

@classmethod
@ndb.tasklet
def get_or_insert_index_entity(cls, verb):
    ent = yield cls._SEARCH_INDEX_DB_MODEL.get_by_id_async(verb)
    if not ent:
        key = ndb.Key(cls._SEARCH_INDEX_DB_MODEL, verb)
        ent = cls._SEARCH_INDEX_DB_MODEL(key=key, name=verb)
        yield ent.put_async()

    raise ndb.Return(ent)

@classmethod
@ndb.tasklet
def txn(cls, verb, entity):
    ent = yield cls.get_or_insert_index_entity(verb)
    if not entity.key in ent.reference_list:
        ent.reference_list.append(entity.key)
        yield ent.put_async()
    raise ndb.Return(ent)

@classmethod
def store_list_in_index(cls, list, entity):
    put_queue = []
    for verb in list:
        put_queue.append(cls.txn(verb, entity))

将@ ndb.toplevel添加到我的get-request处理程序中。它的速度更快!

我也在https://groups.google.com/forum/?fromgroups#!topic/appengine-ndb-discuss/L4DEsYdEwTE上发布了这个问题,并提供了一些后续问题

1 个答案:

答案 0 :(得分:4)

如果您不等待结果从“ndb.put_multi_async(put_queue)”返回,那么您的Web处理程序可能会在实际处理请求之前完成。检查put_multi_async函数的返回值。这是期货清单。

要等待一个Future完成,你可能会说fut.get_result()(如果你不关心返回值,还是fut.wait())。如果你有一堆未来,你可能想要在http://code.google.com/appengine/docs/python/ndb/futureclass.html描述的Future.wait_all wait_any