2012-09-04 62 views
10

我有一個調用少量tasklet的POST方法。這些tasklet在它們中確實有產量,而且我的代碼中有一些x.put_async()。所以我不希望它在所有異步內容完成之前都返回。所以我裝飾了我所有的小工具,這些小工具都是@ndb.tasklet。此外,在我的POST方法的頂部,我有:在Google App Engine中使用@ ndb.tasklet或@ ndb.synctasklet

@ndb.toplevel 
def post(self): 

然而,在documentation它指出:

但如果處理方法使用收益率,這種方法仍然需要 裹着另一個裝飾者,@ ndb.synctasklet;否則, 會停止在收益率執行而未完成。

確實我的方法有收益。它已經包裝在@ ndb.tasklet中。我是否用@ ndb.synctasklet替換它,還是兩者都使用(如果是這樣,我將如何使用兩者)?

此外,請參閱this thread它有一些相關性。我也注意到一個問題,即我的請求會返回而沒有任何輸出,但是不可重現。它每15分鐘左右持續使用一次。我只有app = ndb.toplevel(webapp2.WSGIApplication([..]),但現在我已將@ndb.toplevel添加到主要的POST方法中,但問題仍然存在。

我應該把@ndb.tasklet放在剛好put_async()的方法之上嗎? (我應該把它放在每種方法的最上面以保證安全嗎?

回答

10

關於處理程序和使用@ ndb.toplevel和@ ndb.synctasklet: 我理解它的方式是您需要在處理程序上使用@ ndb.synctasklet和@ ndb.toplevel。所有的子任務只需要@ ndb.tasklet裝飾器。例如

class Foo(ndb.Model): 
    name = ndb.StringProperty() 

    @ndb.tasklet 
    def my_async(self): 
     .... 
     #do something else that yields 
     raise ndb.Return("some result") 


@ndb.toplevel 
@ndb.synctasklet 
def post(self): 
    foo = Foo(name="baz") 
    yield foo.put_async() 
    yield foo.my_async() 
    .... 

但是,看source,看來@ ndb.toplevel實際上是一個synctasklet反正:

def toplevel(func): 
    """A sync tasklet that sets a fresh default Context. 

    Use this for toplevel view functions such as 
    webapp.RequestHandler.get() or Django view functions. 
    """ 

運行一個小的測試,在該處理的產量和飾有@ ndb.toplevel似乎仍然工作,看起來你可以從處理程序中刪除@ ndb.synctasklet。

關於是否應該包括@ ndb.tasklet上調用put_async()方法: 如果你不是在put_async()產生,那麼你並不需要包括@ ndb.tasklet對周圍的方法(@ ndb.toplevel將處理從put_async()獲取結果)

+12

良好的答覆!規則可以總結如下:(1)如果函數使用「yield」,它應該是ndb.tasklet,ndb.synctasklet或ndb.toplevel。 (2)包裝在ndb.tasklet中的函數返回一個Future(並且你可以產生它或明確地調用get_result())。 (3)ndb.synctasklet就像將其封裝在ndb.tasklet中,但隱式調用get_result()。 (4)ndb.toplevel就像ndb.synctasklet,但也等待所有未完成的操作完成。 –