Home > Software engineering >  Golang: Timing out SQS ReceiveMessage with WaitTimeSeconds vs with Context argument
Golang: Timing out SQS ReceiveMessage with WaitTimeSeconds vs with Context argument

Time:10-20

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.

  • Related