Usar boto para invocar funciones lambda, ¿cómo lo hago de forma asincrónica?

Entonces estoy usando boto para invocar mis funciones lambda y probar mi backend. Quiero invocarlos de forma asíncrona. He observado que “invoke_async” está en desuso y no debe utilizarse. En su lugar, debe usar “invocar” con un Tipo de invocación de “Evento” para realizar la función de forma asíncrona.

Parece que no puedo averiguar cómo obtener las respuestas de las funciones cuando regresan. He probado lo siguiente:

payload3=b"""{ "latitude": 39.5732160891, "longitude": -119.672918997, "radius": 100 }""" client = boto3.client('lambda') for x in range (0, 5): response = client.invoke( FunctionName="loadSpotsAroundPoint", InvocationType='Event', Payload=payload3 ) time.sleep(15) print(json.loads(response['Payload'].read())) print("\n") 

Aunque le digo al código que se duerma durante 15 segundos, la variable de respuesta aún está vacía cuando bash imprimirlo. Si cambio el InvokationType de invocación a “RequestResponse”, todo funciona bien y se imprime la variable de respuesta, pero esto es síncrono. ¿Me estoy perdiendo algo fácil? ¿Cómo ejecuto algún código, por ejemplo, imprimo el resultado, cuando se devuelve la invocación asíncrona?

Gracias.

Una función de AWS Lambda ejecutada de forma asíncrona no devuelve el resultado de la ejecución. Si una solicitud de invocación asíncrona es exitosa (es decir, no hubo errores debido a los permisos, etc.), AWS Lambda devuelve inmediatamente el código de estado HTTP 202 ACEPTADO y no tiene ninguna responsabilidad adicional para comunicar información sobre el resultado de esta invocación asíncrona.

De la documentación de AWS Lambda Invoke action :

Sintaxis de respuesta

 HTTP/1.1 StatusCode X-Amz-Function-Error: FunctionError X-Amz-Log-Result: LogResult Payload 

Elementos de respuesta

Si la acción tiene éxito, el servicio devuelve la siguiente respuesta HTTP.

Código de estado

El código de estado HTTP estará en el rango 200 para una solicitud exitosa. Para el tipo de invocación RequestResponse este código de estado será 200. Para el tipo de invocación de Event este código de estado será 202 . Para el tipo de invocación DryRun el código de estado será 204.

[…]

La respuesta devuelve lo siguiente como el cuerpo HTTP.

Carga útil

Es la representación JSON del objeto devuelto por la función Lambda. Esto está presente solo si el tipo de invocación es RequestResponse .

Hay una diferencia entre una ‘invocación lambda asíncrona de AWS’ y un ‘código de python asíncrono’ . Cuando establece InvocationType en 'Event' , por definición , nunca envía una respuesta.

En su ejemplo, invoke() devuelve inmediatamente None , y no inicia implícitamente nada en el fondo para cambiar ese valor en un momento posterior (¡gracias a Dios!). Entonces, cuando miras el valor de la response 15 segundos después, sigue siendo None .

Parece que lo que realmente quieres es el tipo de invocación RequestResponse , con código Python asíncrono. Tiene un montón de opciones para elegir, pero mi favorito es concurrent.futures . Otro es el threading .

Aquí hay un ejemplo usando concurrent.futures :

(Si está usando Python2, necesitará pip install futures )

 from concurrent.futures import ThreadPoolExecutor import json payload = {...} with ThreadPoolExecutor(max_workers=5) as executor: futs = [] for x in xrange(0, 5): futs.append( executor.submit(client.invoke, FunctionName = "loadSpotsAroundPoint", InvocationType = "RequestResponse", Payload = bytes(json.dumps(payload)) ) ) results = [ fut.result() for fut in futs ] print results 

Otro patrón que podría querer analizar es usar el tipo de invocación de Event y hacer que la función Lambda envíe mensajes a SNS, que luego son consumidos por otra función Lambda. Puede consultar un tutorial para las funciones lambda activadas por SNS aquí .