TypeScriptでAWS SQSを使う

AWS SDK for Javascriptを使って、AmazonSQSを試してみます。

# AmazonSQS
公式サイト：https://aws.amazon.com/jp/sqs/

マイクロサービス、分散システム、およびサーバーレスアプリケーション用の完全マネージド型メッセージキューです。
メッセージの順番が保証されず、ちょっと安く利用できる**標準キュー**と、高スループットでメッセージの順番が保証されている**FIFOキュー**の2種類のキュータイプがあります。

細かい機能は公式サイトを見ていただけたらと思います。

SQSは使用した分で課金される＆一定量を超えない限り課金されない、ので放置していても課金が発生せず、作った後に削除する必要がないのも試しやすい点です。

# AWS SDK for Javascript
公式サイト：https://aws.amazon.com/jp/sdk-for-javascript/

JavaScriptから呼び出すAWS SDKです。AWSのサービスを簡単に使うことができます。
当たり前ですが、今の業務がTypeScript、Node.jsを使っているので、今回はJavaScriptにしていますが、他の言語でも同じように使うことができます。

# AmazonSQSのHello World
コードを書く前に先にSQSをコンソール画面から作成して使ってみます。

ドキュメント：https://aws.amazon.com/jp/getting-started/hands-on/send-messages-distributed-applications/

ドキュメントに載っている通り、Queueを作り、簡単なメッセージの送信と受信をするところをやります。

Amazon SQSの画面に進み、`Create queue`でQueueを作ります。
Typeは簡単な動作を見るだけなので、今回は`Standard`にします。

![スクリーンショット 2023-07-02 21.41.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/72812938-c4c2-0504-20cf-db2ba0bb0aa4.png)

キュー作成後、`Send and receive messages`を押し、`Send Message`でメッセージの送信、`poll for messages`でメッセージの取り出しをします。

![2023-02-23_23-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/834d3f8c-52a3-3ad0-3f61-d882c9691268.png)

キュー作りはこれで終わりです。簡単ですね。

# AWS SDK for Javascriptでメッセージの送信＆受信＋イベントを実行する
メッセージの送信＋受信を確認して、SQS→Lambda→Slack通知あたりをする簡単なシステムを作ってみます。

## IAMユーザの作成
今回はSQSへのアクセスからローカルから行う際にIAMユーザを使いますので、そのユーザを作ります。
必要なポリシーとしては、SQSの`ReceiveMessage`と`SendMessage`になります。

![スクリーンショット 2023-07-02 21.54.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/ac3fcc05-c071-8f7f-d6d1-1cb7c9fbef97.png)

## メッセージの送信（と受信）
`@aws-sdk/client-sqs`というパッケージを使います。
ドキュメントは下記。(概要はドキュメントの方がわかりやすいですが、型などで記載がないものがあったので、細かいところはコードから参照した方が良さそうです。)
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-sqs/

今回はメッセージの送信と受信（動作確認だけ）を行うので、`SQSClient`と
`SendMessageCommand`と`ReceiveMessageCommand`を使います。

最初にSQSを触るためのクライアントである`SQSClient`のインスタンスを作ります。
今回は必要な権限を持つIAMユーザを作成し、そのアクセスキーを使います。

クレデンシャルの指定は、下記のように指定するとできます。
```ts
const sqs_client = new SQSClient({
  credentials: {
    accessKeyId: 'test', // AWS access key ID
    secretAccessKey: 'test', // AWS secret access key
  }
});
```

Node.jsに認証情報をロードする方法として、環境変数で指定された認証情報ファイルからの読み込み、環境変数からの読み込みがあります。
上記のようにconstructorで指定しない場合、認証情報ファイルの環境変数`AWS_PROFILE`や`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`の情報が設定されます。

次にメッセージの送信と受信ですが、これもドキュメントを読んで書くだけになります。細かいところは割愛しますが、下記のようなコードで動きます。

メッセージの送信
```ts
const params = {
  QueueUrl: `${キューのURL}`,
  MessageBody: `${メッセージのボディ}`,
  DelaySeconds: 10,
};
const command = new SendMessageCommand(params);
await sqs_client.send(command);
```

メッセージの受信
```ts
const params = {
  AttributeNames: ["SentTimestamp"],
  MaxNumberOfMessages: 1,
  MessageAttributeNames: ["All"],
  QueueUrl: `${キューのURL}`,
  WaitTimeSeconds: 10,
};
const command = new ReceiveMessageCommand(params);
await sqs_client.send(command);
```

ここまでできたら、実際にキューにメッセージを送信・受信を試します。
キューに入ったメッセージは、コンソール画面で簡単に確認できます。

実装例のGithub：https://github.com/KouheiHara/AWSForJavascript

# Lambdaの設定
Lambdaの設定としては、SQSをトリガーを設定し、受け取ったメッセージのテキストを通知するようにします。
Lambdaのトリガーの設定時、SQSのメッセージの受信などをするため、Roleの設定が必要になります。今回はLambdaに割り当てるので、AWS Service Roleを作ります。

`Trust relationships`の`Principal`の`Service`を`lambda`に設定します。（これでLambda側から紐づけることができるようになります。）
![スクリーンショット 2023-07-02 22.04.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/c55bbcbc-8d15-8672-9366-b427d15168ae.png)

後はSQSをトリガーとして設定するのに、必要なポリシーを設定するだけです。これはトリガーの設定時に必要なポリシーを教えてくれるので、その必要な分だけ設定します。

![スクリーンショット 2023-07-02 22.07.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/4516b27e-2671-ea08-52de-6cff008e024f.png)

Slack通知はSlack APIを使います。今回は`chat.postMessage`APIでメッセージを送ります。
https://api.slack.com/methods/chat.postMessage`

SQSから受け取ったメッセージのbodyを受け取り、下記のようなコードSlack通知を行います。

```js
exports.handler = async (event) => {
  const text = event.Records[0].body;
  const payload = {
    channel: 'My Channel',
    blocks: [
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": text,
        }
      },
    ],
  };

  const options = {
    hostname: 'slack.com',
    port: 443,
    path: '/api/chat.postMessage',
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer Token'
    }
  };

  const res = await request(
    options,
    JSON.stringify(payload),
  );
  console.log('statusCode:', res.statusCode);

  return { statusCode: 200, body: 'OK' };
};
```


あとは、SQSにメッセージを送信すると、Slackに通知されることを確認して終わりです。

![スクリーンショット 2023-07-02 22.14.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/1bc2608e-37c8-cb51-cae0-15895d71f158.png)

# まとめ

AWS SDK for JavascriptでSQSへのメッセージの送信、Lambdaでメッセージ受信、Slack通知まで行いましたが、便利なのに対して、比較的に簡単なので、色々なところで使えそうかなと思いました。

あとは、私だけかもしれませんが、AWS SDKのドキュメントが新しくなって、逆に読みにくくなったと感じました。