Creación de un método asíncrono con el NDB de Google App Engine

Quiero asegurarme de que descubrí cómo crear tasklets y métodos asíncronos. Lo que tengo es un método que devuelve una lista. Quiero que se llame desde algún lugar, e inmediatamente permitir que se realicen otras llamadas. Así que tengo esto:

future_1 = get_updates_for_user(userKey, aDate) future_2 = get_updates_for_user(anotherUserKey, aDate) somelist.extend(future_1) somelist.extend(future_2) .... @ndb.tasklet def get_updates_for_user(userKey, lastSyncDate): noteQuery = ndb.GqlQuery('SELECT * FROM Comments WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastSyncDate) note_list = list() qit = noteQuery.iter() while (yield qit.has_next_async()): note = qit.next() noteDic = note.to_dict() note_list.append(noteDic) raise ndb.Return(note_list) 

¿Está este código haciendo lo que yo esperaría que hiciera? A saber, ¿las dos llamadas se ejecutarán de forma asíncrona? ¿Estoy usando futuros correctamente?

Edición: Bueno, después de la prueba, el código produce los resultados deseados. Soy un novato en Python. ¿Cuáles son algunas maneras de probar si los métodos se ejecutan de forma asíncrona?

Es bastante difícil verificar por ti mismo que los métodos se ejecutan de forma simultánea; tendrías que hacer un registro abundante. Además, en el servidor de aplicaciones dev será aún más difícil, ya que en realidad no ejecuta RPC en paralelo.

Tu código se ve bien, usa el yield en el lugar correcto.

Mi única recomendación es nombrar su función get_updates_for_user_async() – que coincida con la convención que usa el propio NDB y es una sugerencia para el lector de su código de que la función devuelve un Futuro y debe obtenerse para obtener el resultado real.

Una forma alternativa de hacer esto es usar el método map_async() en el objeto Query ; le permitiría escribir una callback que solo contiene la llamada to_dict() :

 @ndb.tasklet def get_updates_for_user_async(userKey, lastSyncDate): noteQuery = ndb.gql('...') note_list = yield noteQuery.map_async(lambda note: note.to_dict()) raise ndb.Return(note_list) 

Sugerencia avanzada: puede simplificar esto aún más al @ndb.tasklet decorador @ndb.tasklet y devolver el futuro devuelto por map_async() :

 def get_updates_for_user_Async(userKey, lastSyncDate): noteQuery = ndb.gql('...') return noteQuery.map_async(lambda note: note.to_dict()) 

Esta es una ligera optimización general para funciones asíncronas que contienen solo un rendimiento y devuelven inmediatamente el valor obtenido. (Si no obtienes esto de inmediato, estás en buena compañía y corre el riesgo de que lo rompa un futuro mantenedor que tampoco lo haga. 🙂