2012-09-04 7 views
10

Tengo un método POST que llama a algunas tasklets. Estos tasklets tienen rendimientos en ellos, y tengo algunos x.put_async() en mi código. Así que no quiero que vuelva antes de que todas las cosas de sincronización estén hechas. Así que decoré todas mis tareas, que son solo pequeñas funciones con @ndb.tasklet. Además, en la parte superior de mi método POST, que tengo:Usando @ ndb.tasklet o @ ndb.synctasklet en Google App Engine

@ndb.toplevel 
def post(self): 

Sin embargo, en el documentation afirma:

Pero si un método de controlador utiliza el rendimiento, este método todavía tiene que ser envuelto en otro decorador, @ ndb.synctasklet; de lo contrario, dejará de ejecutarse en el rendimiento y no finalizará.

De hecho, mi método tiene un rendimiento. Ya está incluido en @ ndb.tasklet. ¿Sustituyo esto con @ ndb.synctasklet o utilizo ambos (de ser así, cómo usaría ambos)?

También, vea this thread que tiene alguna relevancia. También noté un problema en el que mi solicitud volvería sin ningún resultado, pero no es reproducible. Sucede cada 15 minutos más o menos de uso constante. Tenía app = ndb.toplevel(webapp2.WSGIApplication([..]) solamente, pero ahora he agregado @ndb.toplevel a los métodos principales POST, pero el problema persiste.

¿Debo poner @ndb.tasklet encima de los métodos que tienen solo put_async() también? (Lo pongo en la parte superior de cada método sólo para estar seguro ¿Cuáles son las desventajas de este??)

Respuesta

10

En cuanto a la guía y usando @ @ ndb.toplevel y ndb.synctasklet: La forma en que entendí fue que necesita usar tanto @ ndb.synctasklet como @ndb.toplevel en el controlador. Todas las subtareas solo necesitan el decorador @ ndb.tasklet. p.ej.

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

Sin embargo. mirando el source, parece que @ ndb.toplevel es en realidad un synctasklet todos modos:

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

funcionamiento de una pequeña prueba con rendimientos en el controlador y decorado con @ ndb.toplevel todavía parece funcionar, y parece que puede eliminar @ ndb.synctasklet del controlador.

En cuanto a si se debe incluir @ ndb.tasklet en métodos que requieren put_async(): Si usted no está produciendo en el put_async(), entonces no es necesario incluir @ ndb.tasklet en el método que rodea (@ ndb.toplevel se encargará de obtener los resultados de put_async())

+12

¡Buena respuesta! Las reglas se pueden resumir de la siguiente manera: (1) si una función usa "rendimiento", debe ndb.tasklet, ndb.synctasklet o ndb.toplevel. (2) una función envuelta en ndb.tasklet devuelve un futuro (y puede cederlo o llamar a get_result() explícitamente). (3) ndb.synctasklet es como envolverlo en ndb.tasklet pero implícitamente llamar a get_result(). (4) ndb.toplevel es igual que ndb.synctasklet pero también espera a que se completen todas las operaciones pendientes. –