The VisibilityTimeout
in SQS is a straightforward concept according to the official doc. It is a time frame that the message can be hidden so that no others can consume it except the first consumer who calls the ReceiveMessage
API. And the maximum value of VisibilityTimeout
is 43200
seconds or 12 hours.
However the API ChangeMesssageVisibility
is tricky because the doc on AWS is too vague.
For example, you have a message with a visibility timeout of 5 minutes. After 3 minutes, you call
ChangeMessageVisibility
with a timeout of 10 minutes. You can continue to callChangeMessageVisibility
to extend the visibility timeout to the maximum allowed time. If you try to extend the visibility timeout beyond the maximum, your request is rejected.
It is very confusing because you cannot tell what does that mean. If you poke around for some lauguage specific docs such as Java, or Go, things “seems” become clearer. There is a parameter called VisibilityTimeout
in the request of ChangeMessageVisibility
API, and, according to the doc it means
The new value for the message’s visibility timeout (in seconds). Values range:
0
to43200
. Maximum: 12 hours.
OK, now you may feel you understand how it works. As long as you still have the message handle, you can call this API to change its VisibilityTimeout
to any new value as long as the value is between 0 and 43200. However that’s not the case.
Take a look at the following Go code snippet
What do you think the output of this program? You may think, well, the message is retrieved with VisibilityTimeout
30 seconds, then the program sleeps for 10
seconds(you can think of it as the program is doing some business logic that takes 10 seconds), then it tries to change the message’s visibility timeout to a new value 43191
seconds (< 12 hours) because the program maybe doesn’t want other consumer to consume it for 43191
seconds, fair.
However the program actually ends up in L43 and prints out an error that says
operation error SQS: ChangeMessageVisibility, https response error StatusCode: 400, RequestID: d6a5bb0e-ef0a-5874–80fa-e2b231a17d11, api error InvalidParameterValue: Value 43191 for parameter VisibilityTimeout is invalid. Reason: Total VisibilityTimeout for the message is beyond the limit [43200 seconds]
What?! 43191 is between 0 and 43200, why it cannot be set?
OK, that’s because after you retrieved the message at L27, time has lapsed for 10
seconds(L35), and SQS rejects it because
10 + 43191 > 43200
So the parameter VisibilityTimeout
of the request of ChangeMessageVisibility
API actually means from the time the ChangeMessageVisibility
request is made, how much more time the message is invisible to others. And the total timeout cannot exceed 43200
. (Not the parameter cannot exceed 43200!)
I cannot find the implementation of that API, however I found this resource probably reflects what the implementation is. I think AWS should really fix the doc of this API.