I can call SQS ReceiveMessage with
sqs.ReceiveMessageInput{
QueueUrl: &mysqr.poolQUrl,
MaxNumberOfMessages: 1,
WaitTimeSeconds: 5,
}
and context.TODO(), or with
ctx := context.Background()
ctx2, cfn := context.WithTimeout(ctx, time.Second * 5)
defer cfn()
rmo, err := svc.ReceiveMessage(ctx2, &rmi)
Let's assume there's nothing available to read in 5 seconds.
In the first case, it returns fine with no messages and no errors, in the second I get a operation error SQS: ReceiveMessage, https response error StatusCode: 0, RequestID: , canceled, context deadline exceeded
.
It was nice of AWS to put context in the go SDK, but I'd rather use the WaitTimeSeconds argument, it just feels simpler. Is there a good principled reason to use the context
approach instead?
CodePudding user response:
It was nice of AWS to put context in the go SDK
You're conflating the WaitTimeSeconds
, part of ReceiveMessages
API, with the Timeout that you could potentially attach to a context.
WaitTimeSeconds is an important part of long polling SQS Queues. Without it, empty queues would cause consumers to make api requests as quickly as possible, driving huge loads on AWS. Exceeding the WaitTimeSeconds
does not indicate errors - the request could legitimately take even many extra seconds on a degraded network.
Contexts can be used to abort SDK operations for reasons outside the realm of the SDK itself - WithTimeout
is only one such use of contexts. In a multithreaded application, you might also use a context to cancel multiple outstanding requests due to some fatal error elsewhere in the application.
So, firstly, thinking of WaitTimeSeconds
as a timeout is incorrect. Secondly, thinking of Context
as a timeout is also incorrect - a context is much more than just controlling max runtime.
but I'd rather use the WaitTimeSeconds argument, it just feels simpler.
They do different things. Context.WithTimeout
doesn't obviate WaitTimeSeconds
. Without WaitTimeSeconds
(or a default setting on the queue), ReceiveMessages
would return immediately and Context.WithTimeout
would never get a chance to time anything out.
Is there a good principled reason to use the context approach instead?
So no, certainly not. There's a good reason to use contexts in addition to WaitTimeSeconds
- even Context.WithTimeout
might make sense with ReceiveMessages
requests in some situations. But even though they both take durations, there is no overlap in use case. With or without a context, it's almost never correct to run ReceiveMessages
with WaitTimeSeconds
set to 0.