5

エンティティを更新してデータストアに保存し、戻る前に追加の作業を実行する必要があるリクエストハンドラーがあります(バックグラウンドタスクのキューイングやjson-いくつかの結果のシリアル化など)。このコードを並列化して、エンティティの保存中に追加の作業が行われるようにします。

これが私のハンドラーコードの要約です:

class FooHandler(webapp2.RequestHandler):
    @ndb.toplevel
    def post(self):
        foo = yield Foo.get_by_id_async(some_id)

        # Do some work with foo

        # Don't yield, as I want to perform the code that follows
        # while foo is being saved to the datastore.
        # I'm in a toplevel, so the handler will not exit as long as
        # this async request is not finished.
        foo.put_async()

        taskqueue.add(...)
        json_result = generate_result()
        self.response.headers["Content-Type"] = "application/json; charset=UTF-8"
        self.response.write(json_result)

ただし、Appstatsは、datastore.PutRPCが次の後にシリアルに実行されていることを示していtaskqueue.Addます。

Appstatsのスクリーンショット

少し掘り下げてみると、RPCがすぐに発行されるのではなくndb.context.pyput_async()呼び出しが追加されることになります。AutoBatcher

したがって、すべての非同期呼び出しが完了するのを待つと、最終的_put_batcherにフラッシュされると思います。toplevel

プットのバッチ処理には特定のシナリオで実際のメリットがあることを理解していますが、ここでの私の場合は、プットRPCをすぐに送信して、エンティティの保存中に他の作業を実行できるようにします。

そうした場合yield foo.put_async()、Appstatsで同じウォーターフォールを取得しますがdatastore.Put、残りの前に実行されます。

2番目のAppstatsスクリーンショット

yieldハンドラーがput_async()呼び出しが完了するのを待ってから残りのコードを実行するので、これは予想されることです。

ndb.get_context().flush()また、直後に呼び出しを追加しようとしましたfoo.put_async()が、Appstatsによると、datastore.Puttaskqueue.BulkAdd呼び出しはまだ並行して行われていません。

put_async()だから私の質問は:自動バッチャーをバイパスしてRPCをすぐに発行するように呼び出しを強制するにはどうすればよいですか?

4

2 に答える 2

6

サポートされている方法はありません。多分あるはずです。これがうまくいくか試してみませんか?

loop - ndb.eventloop.get_event_loop()
while loop.run_idle():
    pass

ndb / eventloop.pyのソースコードを調べて、他に何を試すことができるかを確認する必要があるかもしれません。基本的には、RPCを待つことを除いてrun0()が行うことのほとんどを試したいと思います。特に、これを行う必要がある可能性があります。

while loop.current:
    loop.run0()
while loop.run_idle():
    pass

(これはまだサポートされていません。他にも処理しなければならない条件があるためですが、これらはあなたの例では発生していないようです。)

于 2013-02-22T15:58:57.850 に答える
-2

これを試してみてください、私はそれが役立つと100%確信していません:

foo = yield Foo.get_by_id_async(some_id)
future = foo.put_async()
future.done()

ndbリクエストはオートバッチャーに入れられ、結果が必要なときにバッチがRPCに送信されます。foo.put_async()の結果は必要ないため、別のndb呼び出しを行うまで(必要ない)、または@ndb.toplevelが終了するまで送信されません。

future.done()を呼び出してもブロックされませんが、リクエストがトリガーされる可能性があると思います。

操作を強制しようとするもう1つのことは、次のとおりです。

ndb.get_context().flush()
于 2013-02-21T17:24:10.920 に答える