SQSでメッセージ受信回数による処理切り分けをしたい

SQSのVisibility Timeoutを使って再実行をするのはいいんだけれども、無効な命令が投げられてたりした場合には有限で終了して欲しいので、それを実現するにはどうすればいいのかというお話。

幾つか方法はあるけれども、主に考えられるのは2つ。

MessageのAttributeを利用する

AWS Management ConsoleでQueueのメッセージを見る場合に "count" という文字がでているので、どこかにはデータを持っているっぽかったので、それを探してみた結果、一応あった。

ただし、パラメータ名は count では無く、 ApproximateReceiveCount になっている。

しかもこの要素を使おうとした場合、メッセージ取得時にパラメータを入れないと取れない。

botoの場合は以下のようにしてメッセージを持ってくれば良い。

import boto.sqs

conn = boto.sqs.connect_to_region('ap-northeast-1')
my_queue = conn.get_queue('myqueue')
msgs = my_queue.get_messages(attributes='ApproximateReceiveCount')

if len(msgs) > 0:
  count = int(msgs[0].attributes['ApproximateReceiveCount'])

Approximate とあるので、正しい値ではないのかも知れないが、自分が考えている用途ではこの値で十分だった。

IDで判定

取得したMessageには固有のIDがあるので、これが何回出現したかをカウントする。
回数を自分で数えるので、正確な回数が保証したい場合はこれになるのかな。