Using boto3 to await a synchronous lambda invocation

Viewed 731

I want to invoke a lambda function synchronously (request - response) but want to use python async-await to await the response.

    response = await client.invoke('my-func', InvocationType='RequestResponse', Payload='...'))

I found a kind of solution here but it is cumbersome and from 2016.

Is there a better approach today?

1 Answers

I found a way of doing it by manually running the invoke function on the asyncio event loop:

import asyncio
import concurrent
import boto3
import json

import botocore


class LambdaClient():
    def __init__(self, concurrency: int = 20):
        self.executor = concurrent.futures.ThreadPoolExecutor(
            max_workers=concurrency,
        )
        client_config = botocore.config.Config(
           max_pool_connections=concurrency
        )
        self.client = boto3.client('lambda', config=client_config)
    
    async def invoke_async(self, snapshot):
        loop = asyncio.get_running_loop()
        result = await loop.run_in_executor(self.executor, lambda: self.invoke(snapshot))
        return result

    def invoke(self, snapshot):
        payload = {
        'path': '/calculate/value',
        'body': json.dumps(snapshot)
        }
        b = bytes(json.dumps(payload), encoding='utf8')
        response = self.client.invoke(
            FunctionName='function-name',
            InvocationType='RequestResponse',
            LogType='None',
            Payload=b)
        if 'StatusCode' not in response or response['StatusCode'] != 200:
            raise ValueError(f'Lambda invocation failed with response {response}')
        output = response["Payload"].read()
        return output
Related