簡體   English   中英

如何覆蓋異步 NDB 方法並編寫自己的 tasklet

[英]How to override an async NDB method and write your own tasklet

我正在嘗試掌握 NDB 引入的異步操作,我想使用@ndb.tasklet來異步我的一些工作。

簡單的例子是在覆蓋的 get_or_insert_async 中生成get_or_insert_async

這是處理事情的正確方法嗎? 這里有什么可以改進的?

@classmethod
@ndb.tasklet
def get_or_insert_async(cls, *args):
    id = cls.make_string_id(*args) 
    model = yield super(MyModel, cls).get_or_insert_async(id)
    raise ndb.Return(model)

另一個例子是以扇出的方式在循環中做一些事情。 這個對嗎?

@classmethod
@ndb.tasklet
def do_stuff(cls, some_collection):

    @ndb.tasklet
    def internal_tasklet(data):
        do_some_long_taking_stuff(data)
        id = make_stuff_needed_for_id(data)
        model = yield cls.get_or_insert_async(id)
        model.long_processing(data)
        yield model.put_async()
        raise ndb.Return(None)

    for data in some_collection:
        # will it parallelise internal_tasklet execution? 
        yield internal_tasklet(data)

    raise ndb.Return(None)

編輯:

正如對整個概念的理解, yields在這里提供一個Future對象,然后並行收集(在可能的情況下)並異步執行。 我對么?

在 Nick 的提示之后(是你的意思嗎?):

@classmethod
@ndb.tasklet
def do_stuff(cls, some_collection):

    @ndb.tasklet
    def internal_tasklet(data):
        do_some_long_taking_stuff(data)
        id = make_stuff_needed_for_id(data)
        model = yield cls.get_or_insert_async(id)
        model.long_processing(data)
        raise ndb.Return(model)                # change here

    models = []
    for data in some_collection:
        # will it parallelise internal_tasklet execution? 
        m = yield internal_tasklet(data)       # change here
        models.appedn(m)                       # change here

    keys = yield ndb.put_multi_async(models)   # change here
    raise ndb.Return(keys)                     # change here

編輯:

新修訂版…

@classmethod
@ndb.tasklet
def do_stuff(cls, some_collection):

    @ndb.tasklet
    def internal_tasklet(data):
        do_some_long_taking_stuff(data)
        id = make_stuff_needed_for_id(data)
        model = yield cls.get_or_insert_async(id)
        model.long_processing(data)
        raise ndb.Return(model)                

    futures = []
    for data in some_collection:
        # tasklets won't run in parallel but while 
        # one is waiting on a yield (and RPC underneath)  
        # the other will advance it's execution 
        # up to a next yield or return
        fut = internal_tasklet(data))          # change here
        futures.append(fut)                    # change here

    Future.wait_all(futures)                   # change here

    models = [fut.get_result() for fut in futures]
    keys = yield ndb.put_multi_async(models)   # change here
    raise ndb.Return(keys)                     # change here

如果你想做的只是用不同的 arguments 調用一些異步的東西,你不需要使用 tasklets - 只需返回包裝函數的返回值,就像這樣:

def get_or_insert_async(cls, *args):
  id = cls.make_string_id(*args)
  return super(MyModel, cls).get_or_insert_async(id)

不過,出於以下幾個原因,我對此持謹慎態度:您正在更改內置 function 的含義,這通常是個壞主意,您正在更改簽名(位置 arguments 但沒有關鍵字參數),並且您'沒有將額外的 arguments 傳遞給原來的 function。

對於你的第二個例子,一次產生一個東西將迫使 NDB 等待它們完成——'yield' 是 'wait' 的同義詞。 相反,為集合中的每個元素執行 tasklet function,然后同時等待它們(通過調用列表上的 yield)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM