SQSをRubyで操作している。
APIを用いてSQSのキューの中のメッセージを取得しようとしている。
receive-messageを用いているがなぜか4件中1件しか取得できない。
調べたところポーリング時間を長くすればいいと分かったのだが、できない、、、、
これはポーリング時間を長くするための戦いの記録である。
##コード
require "aws-sdk"
require "json"
require "pry-rails"
#aws アカウントの設定
sqs = Aws::SQS::Client.new()
#sqsからデータをロード
## キューに入れたmessage達を取得
queue_url = ENV['AWS_SQS_DEVELOP_CATEGORY_KEY']
receive_message_result = sqs.receive_message(
queue_url: queue_url,
wait_time_seconds: 5,
max_number_of_messages: 10
)
wait_time_seconds: 5でポーリング時間を正しく設定できていると思ったのだが、そんなことなかった。
さて、、、
##仕組みの理解
かなり検索しても原因が分からなかったので根本を理解していないといけない系の問題と判断。ここからsqsのシステム説明に入ります。
参考になったのはこちらのQiita記事。SQSについての基本的なことが書かれている。
これを読んでみると、
SQSは全て取得できることを保証しない
とある。結構いい加減なのか?
ロングポーリングに関しても、ポーリング時間不足で起こる空のメッセージ受信を防ぐための物のようで、今回の問題は解決しなさそう。
進展
探していたところ、以下の記述をDocument内にて発見
If the number of messages in the queue is small (fewer than 1,000), you most likely get fewer messages than you requested per ReceiveMessage call. If the number of messages in the queue is extremely small, you might not receive any messages in a particular ReceiveMessage response. If this happens, repeat the request.
訳すと、「キュー内のメッセージがとても少ないと特定のメッセージを取得できない可能性があるので、その場合はリクエストを繰り返してください。」と書いてある。
#結論
SQSの仕様?で少なすぎるメッセージは希望件数取得できないみたい。なのでメッセージの取得、削除を繰り返して全件取得を繰り返すことにする。
#メッセージ取得
receive_message_result = sqs.receive_message({
queue_url: queue_url,
attribute_names: ["All"], # Receive all available built-in message attributes.
message_attribute_names: ["All"], # Receive any custom message attributes.
max_number_of_messages: 10, # Receive up to 10 messages, if there are that many.
wait_time_seconds: 5
})
while !receive_message_result.messages.nil?
receive_message_result.messages.each do |message|
# 〜〜〜操作〜〜〜
# 操作後のメッセージ削除
sqs.delete_message({
queue_url: queue_url,
receipt_handle: message.receipt_handle
})
end
# 再度メッセージ取得
receive_message_result = sqs.receive_message({
queue_url: queue_url,
attribute_names: ["All"], # Receive all available built-in message attributes.
message_attribute_names: ["All"], # Receive any custom message attributes.
max_number_of_messages: 10 # Receive up to 10 messages, if there are that many.
})
end
こんな感じにすることにした。
もっといい方法があれば教えてください。
終わり