2012-02-29 16 views
2

私は非同期APIの周りに頭を抱えようとしていますが、大した成功はありません。NDB非同期APIとget_or_insert_async

私の研究室プロジェクトではかなり簡単な設定です。

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

そしてreference_listはキーが含まれている場合、それを追加しない場合は、get_or_insertとチェックを使用する方法:私はこのようになりますモデルを持っています。エンティティの下にはこれは私が望んでいたとして働いていたが、looong時間に

@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) 

[「GHI」、「DEF」、「ABC」]モデルのエンティティであり、リストは、文字列のリストです。リストが約20-30倍長い場合。それは約15-20秒かかりました。

私は非同期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) 

私は本当にどこ理解していない、私はタスクレットや歩留まりの概念を理解していないので、主に。誰もが何らかのアイデアを持っているか、私の方向を指すことができますか?

EDIT:

@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)) 

そして、私のGETリクエストハンドラへの@ ndb.toplevelを追加:

私はこの解決策になってしまいました。それは速いです!

私もhttps://groups.google.com/forum/?fromgroups#!topic/appengine-ndb-discuss/L4DEsYdEwTEに、この質問を投稿し、結果はあなたの「ndb.put_multi_async(put_queue)」から戻ってくるためにあなたは、あなたのウェブハンドラのかもしれませんが、待っていない場合は、いくつかの質問

+1

appengine-ndb-discussリストに返信しています。 –

答えて

4

をフォローアップが含まれています実際にリクエストを行う前に完了してください。 put_multi_async関数の戻り値を確認してください。それは先物のリストです。

未来が終わるのを待つには、fut.get_result()(または戻り値を気にしない場合はfut.wait()と言うかもしれません)。先物がたくさんある場合は、おそらくFuture.wait_all wait_anyの説明がhttp://code.google.com/appengine/docs/python/ndb/futureclass.htmlです。

+0

あなたは間違いなしです。しかし、私は@ ndb.toplevelを使用して終了しました。私はuppを使用して終了したソリューションで質問を更新しました。 – fredrik

+0

悲しいことに、私は、最初にこの問題の周りにあなたの脳を包み込むことをとても難しくしたドキュメンテーションを書いたテクニカルライターです。だから、脳のラッピングを簡単にする方法についての提案があれば、話してください。 –

+0

主に私は、異なるデコレータが何をしているのか、それらの違いについて言います。さらにいくつかの例があります。たとえば、タスクレットを使用する場合と.get_resultを使用する場合のベストプラクティスです。これは最高の場所のディスクルルではないかもしれません。あなたの電子メールを見つけることができませんでしたが、あなたが私を1つドロップすることができれば(プロフィールのメール)、これを改善するための良いアイディアがいくつかあります。 – fredrik