はじめに
先日AWSのSQSを使ってSQS内にあるメッセージを別のキューに送信した後に元のキューの処理済みメッセージを削除するシステムを構築した際に、そこで使用されていた2つのメソッドを検証したところ、要注意な仕様があったのでここにまとめておく。
目次
1. そもそもsendMessageBatch・deleteMessageBatchとは?
- sendMessageBatchとは?
- deleteMessageBatchとは?
2. 気をつけなければいけない仕様とは?
- 一部処理に失敗しても、ステータスコード200が返ってくる場合がある
- 特にこのケースには要注意
3. 一部処理に失敗したときに処理を分けるには?
- Failedを活用する
そもそもsendMessageBatch・deleteMessageBatchとは?
sendMessageBatchとは?
-
数多く存在するAWSのSQSに存在するメソッドの中の一つ。(参照:JavaScript API リファレンス
-
指定されたキューに対して最大10個のメッセージを送信するというもの。
-
似たようなものにメッセージを一件だけ送信するsendMessageが存在するが、そのバッチ処理バージョンがこれ。
-
このメソッドを呼び出すと、以下のように送信に成功したメッセージを失敗したメッセージをリストで返してくれる。
SendMessageBatchResult { //送信結果のオブジェクト
Successful: SendMessageBatchResultEntryList; //送信に成功したメッセージのリスト
Failed: BatchResultErrorEntryList; //送信に失敗したメッセージのリスト
}
deleteMessageBatchとは?
-
このメソッドも数多く存在するAWSのSQSに存在するメソッドの中の一つ。(参照:JavaScript API リファレンス
-
指定されたキューから最大10個のメッセージを削除するというもの。
-
このメソッドも似たようなものにメッセージを一件だけ送信するdeleteMessageが存在するが、そのバッチ処理バージョンがこれ。
-
このメソッドを呼び出すと、以下のように削除に成功したメッセージを失敗したメッセージをリストで返してくれる。
DeleteMessageBatchResult { //削除結果のオブジェクト
Successful: DeleteMessageBatchResultEntryList; //削除に成功したメッセージのリスト
Failed: BatchResultErrorEntryList; //削除に失敗したメッセージのリスト
}
気をつけなければいけない仕様とは?
一部処理に失敗しても、ステータスコード200が返ってくる場合がある
-
注意しなければいけないのは、この二つのメソッドはバッチ処理で、まとめて処理するものであるということ。
-
そのため仮に10件処理したとして、そのうち2件なんらかの原因で処理に失敗したとしてもエラーが発生せず、ステータスコード200が返ってくる場合がある。
特にこのケースには要注意
-
例えば、sendMessageBatchであるSQSにメッセージを10件送信した後にそのSQSからそれらのメッセージdeleteMessageBatchで削除するとする。
-
その場合、それぞれのメソッドは一部失敗したとしてもエラーにならないので、仮にsendMessageBatchに一部失敗したとしても、deleteMessageBatchで全件成功してしまう可能性がある。
-
つまり、「送信に失敗したのに削除されてしまったメッセージ」が存在してしまうことになる。
↓↓↓こんな感じ↓↓↓
//たとえばtry~catchなどで例外処理をしてもcatchされない可能性がある
try{
//sendMessageBatchは一部処理に失敗しても処理が続行され、エラーがでない
var sendMessageBatchResult = sqs.sendMessageBatch(キューのURL, 送信対象のメッセージリスト);
//sendMessageBatchで一部処理に失敗しても、以下の処理は実行される
var deleteMessageBatchResult = sqs.deleteMessageBatch(キューのURL, 削除対象のメッセージリスト);
}catch(e){
console.log("エラー");
}
一部処理に失敗したときに処理を分けるには?
- デフォルトではエラーは出されない仕様なので、それぞれのメソッドが返してくれるオブジェクト内の失敗リスト(Failedリスト)を活用する
↓↓↓こんな感じ↓↓↓
//sendMessageBatchを実行して変数sendResultに代入
var sendResult = sqs.sendMessageBatch(キューのURL, 送信対象のメッセージリスト);
if(sendResult.Failed.length != 0){ //リストFailedの長さが0でなければ一部処理が失敗している
throw new Error('一部送信に失敗しました');
}else{
console.log("全件成功しました");
}
//deleteMessageBatchも同様
var deleteResult = sqs.deleteMessageBatch(キューのURL, 処理対象のメッセージ);
if(deleteResult.Failed.length != 0){ //
throw new Error('一部削除に失敗しました');
}else{
console.log("全件成功しました");
}
- sendResult.Failed.lengthとdeleteResult.Failed.lengthにはそれぞれの失敗件数が格納される
- これを活用すれば、何件処理に成功または失敗しているのかを表示させることも可能
- また、sendMessageBatchで処理成功したメッセージリストだけをdeleteMessageBatchの対象にすれば、先ほどの「送信には失敗したけど削除には成功したメッセージ」を回避することができる
↓↓↓こんな感じ↓↓↓
//sendMessageBatchは一部処理に失敗しても処理が続行され、エラーがでない
var sendMessageBatchResult = sqs.sendMessageBatch(キューのURL, 送信対象のメッセージリスト);
//sendMessageBatchで成功したメッセージだけを削除対象にすれば、送信に失敗したものが削除されることはない
var deleteMessageBatchResult = sqs.deleteMessageBatch(キューのURL, sendMessageBatchResult.Successful);