カテゴリー
プログラミング

Chalice(Python)のAPIを叩く(戻り値なしバージョン)

はじめに

ChaliceでバックエンドAPIを実装していました。あるAPIは通知やメール送信などを伴い、レスポンスに時間がかかるようになりました。
そこで、時間がかかる処理は別のChalice(Lambda)を起動してそちらでやってもらい、本線の処理はさっさとレスポンスしてしまおう、と思いつきました。
結果としては失敗で、本線がレスポンスして処理を終えると、非同期で起動したLambdaもつられて終了してしまいました。
結局、やりたいことを実現するにはSQSにキューを投げる→別のLambdaを起動してそちらで時間がかかる処理をする、という構成をとることになりました。
この投稿はそんなダメだったことのメモです。

ソースコード

非同期で別のChalice(Lambda)を叩く関数

Lambdaの環境変数に、Chaliceの関数名 FUNCTION_NAME を設定しておきます。Chaliceで自身の関数名を取得する方法がわからなかったので、一度デプロイして、作成された関数の名前を改めて設定する、というイケテナイ感じになりました…。

def invoke_async_function(
    method: str,
    path: str,
    path_parameters: Dict = {},
    query_string_parameters: Dict = {},
    payload: Dict = {}) -> None:
    """ Invoke lambda asyncnously to execute Chalice app API.
    :params method: The http method on REST.
    :params path: (optional) The path for API. include path parameter placeholders.
    :params path_parameters: (optional) The parameters for the path.
    :params query_string_parameters: (optional) The query string and parameters for the path.
    :params payload: (optional) The data as the request body for API.

    see: How to invoke a Chalice Lambda.
        https://stackoverflow.com/questions/62815740/how-to-directly-invoke-a-chalice-lambda-from-another-lambda-without-going-throug
    
    see: Docs for invoke lambda.
        https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html#Lambda.Client.invoke
    """
    headers: Dict = {}
    if method in ["POST", "PUT", "PATCH"]:
        headers = {
            "Content-Type": "application/json"
        }
    boto3.client("lambda").invoke(
        FunctionName=os.environ.get("FUNCTION_NAME"),
        InvocationType='Event',
        Payload=json.dumps({
            'httpMethod': method,
            'headers': headers,
            'path': path,
            'pathParameters': path_parameters,
            'queryStringParameters': query_string_parameters,
            'multiValueHeaders': {},
            'multiValueQueryStringParameters': None,
            'stageVariables': None,
            'requestContext': {
                'authorizer': {'claims': None},
                'path': path,
                'resourcePath': path,
                'httpMethod': method,
            },
            "body": json.dumps(payload)
        }),
    )

呼び出し方

invoke_async_function(
    "POST",
    "/path/to/{param1}/api/{param2}",
    path_parameters={"param1": param1, "param2": param2},
    payload={"field1": field1, "field2", field2}
)

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください