LoginSignup
8

More than 3 years have passed since last update.

[AWS lambda] Slack Botがタイムアウトで何度もレスポンスするのを防ぐ

Last updated at Posted at 2019-03-11

何度もレスポンスする事例

前の記事で、slack botをAWS lambdaを使って作成しましたが、それの最後に述べたように、何度か同じレスポンスをしてしまう場合があります。
これはslackのタイムアウト時間が3秒しかなく、3秒以内にレスポンスできないとエラーと見なされ、何度か同じイベントを送ってくるため、それに対してlambda関数が何度か呼ばれてしまうことが原因です。
samplebot2.gif

解決方法

新しいlambda関数を作成し、そこから非同期でslackにpostするlambda関数を呼び出すことにする!
このようにすれば、slack APIへのレスポンスは新しいlambda関数からすぐに行うことができ、そのあとでゆっくりとワークスペースにpostMessageすることができます。

新しいlambda関数の作成

IAMロールの作成

前回の記事と同じ手順でロールを作成します。
今回はロールの名前をinvokeBotRoleとしました。
前回と異なるのは、Permissions PoliciesにAWSLambdaBasicExecutionRoleの他にAWSLambdaRoleを追加してください。これによって他のlambda関数を呼び出すことが可能になります。
image.png

lambda関数の作成

前回の記事ではJava縛りで作成しましたが、今回はサクッとPython3.7で作っていきます。
lambdaのページで以下のように設定して、invokeBotというlambda関数を作成しました。
image.png

API Gatewayの作成

これも前回の記事と同様に作成していきます。
今回は、invokeBotAPIという名前のAPIGatewayにして、デプロイ時のステージ名はinvokeBotStageとしました。
デプロイ時に表示されるURLをメモしておくのを忘れないでください。

lambda関数の編集

再びlambda関数のページに戻って編集していきます。
API Gatewayから入って、他のlambda関数に接続できるようになっていることが確認できると思います。
image.png

lambda関数を以下のように編集します。

  • FunctionName='sampleBot'の部分で呼び出すlambda関数の名前を設定しています
  • InvocationType='Event'とすることで非同期の実行が可能になります
  • Slack Event APIの認証にも対応できるようにしています
import json
import boto3
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event: dict, context):

    logging.info(json.dumps(event))
    if "challenge" in event:
        return event.get("challenge")

    client = boto3.client('lambda')
    response = client.invoke(
        FunctionName='sampleBot',
        InvocationType='Event',
        LogType='Tail',
        Payload= json.dumps(event)
    )

    return {
        'statusCode': 200,
        'body': json.dumps('OK')
    }

また、一応念の為lambda関数のtimeout時間も3秒に設定しておくと、確実に3秒以内にslack APIにレスポンスが送られるため安全です。
image.png

イベントのRequest URLに設定

slack APIが呼び出すURLを新しいURLに変更しましょう
先ほどのAPIのデプロイ時にメモしておいたURLを設定し直します
image.png

動作確認

タイムアウトすることなく実行できています!
sampleBot3.gif

参考

AWS LambdaからLambda呼んでハマった話。
AccessDeniedException: User is not authorized to perform: lambda:InvokeFunction

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
8