2012-09-04 10 views
10

Mam metodę POST, która wywołuje kilka zadań. Te zadania mają w nich zyski i mam w moim kodzie trochę x.put_async(). Więc nie chcę, aby powrócił, zanim wszystkie asynchroniczne rzeczy zostaną wykonane. Więc udekorowałem wszystkie moje zadania, które są tylko małymi funkcjami z @ndb.tasklet. Ponadto, na szczycie mojej metody POST, mam:Używanie @ ndb.tasklet lub @ ndb.synctasklet w Google App Engine

@ndb.toplevel 
def post(self): 

Jednak w documentation stwierdza:

Ale jeśli metoda obsługi wykorzystuje wydajność, że metoda nadal musi być zawinięte w inny dekorator, @ ndb.synctasklet; w przeciwnym razie przestanie działać przy wydajności i nie zakończy się.

Rzeczywiście moja metoda ma wydajność. Jest już zapakowany w @ ndb.tasklet. Czy zastąpię to za pomocą @ ndb.synctasklet, czy też używam obu (jeśli tak, to w jaki sposób mogę użyć obu)?

Zobacz także this thread, która ma pewne znaczenie. Zauważyłem również problem, w którym moja prośba powróciłaby bez żadnego wyjścia, ale jest nie do odtworzenia. Zdarza się co 15 minut ciągłego użytkowania. Miałem tylko app = ndb.toplevel(webapp2.WSGIApplication([..]), ale teraz dodałem @ndb.toplevel do głównych metod POST, ale problem nadal występuje.

Czy powinienem wstawić @ndb.tasklet do metod, które mają tylko put_async()? (Należy umieścić go na górze każdej metody dla pewności Jakie są wady do tego?)

Odpowiedz

10

Odnośnie obsługi i korzystania @ ndb.toplevel i @ ndb.synctasklet: Sposób Rozumiałem to, że musisz użyć zarówno @ ndb.synctasklet, jak i @ ndb.toplevel na module obsługi. Wszystkie pod-zadania wymagają tylko dekoratora @ ndb.tasklet. na przykład

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() 
    .... 

Jednak. patrząc na source, wydaje się, że @ ndb.toplevel jest rzeczywiście synctasklet anyway:

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. 
    """ 

Running mały test z wydajnością w programie obsługi i ozdobione @ ndb.toplevel nadal wydaje się działać, i wydaje się, że ciebie może usunąć @ ndb.synctasklet z obsługi.

Odnośnie do tego, czy powinieneś dołączyć @ndb.tasklet do metod, które wywołują put_async(): Jeśli nie ustępujesz na put_async(), to nie musisz dołączać @ ndb.tasklet do otaczającej metody (@ ndb.toplevel obsłuży otrzymanie wyników z put_async())

+12

Dobra odpowiedź! Reguły można podsumować następująco: (1) jeśli funkcja używa "yield", powinno to być ndb.tasklet, ndb.synctasklet lub ndb.toplevel. (2) funkcja owinięta w ndb.tasklet zwraca Future (i możesz ją uodpornić lub wywołać get_result() jawnie). (3) ndb.synctasklet jest podobny do zawijania go w ndb.tasklet, ale niejawnie nazywa się get_result(). (4) ndb.toplevel jest podobny do ndb.synctasklet, ale czeka również na zakończenie wszystkich oczekujących operacji. –