Menu
AWS SDK for Go
Developer Guide

Enabling Long Polling in Amazon SQS Queues

These AWS SDK for Go examples show you how to:

  • Enable long polling when you create an Amazon SQS queue

  • Enable long polling on an existing Amazon SQS queue

  • Enable long polling when a message is received

You can download complete versions of these example files from the aws-doc-sdk-examples repository on GitHub.

Scenario

Long polling reduces the number of empty responses by allowing Amazon SQS to wait a specified time for a message to become available in the queue before sending a response. Also, long polling eliminates false empty responses by querying all of the servers instead of a sampling of servers. To enable long polling, you must specify a non-zero wait time for received messages. You can do this by setting the ReceiveMessageWaitTimeSeconds parameter of a queue or by setting the WaitTimeSeconds parameter on a message when it is received.

The code uses these methods of the Amazon SQS client class:

Prerequisites

  • You have set up and configured the AWS SDK for Go.

  • You are familiar with Amazon SQS polling. To learn more, see Long Polling in the Amazon SQS Developer Guide.

Enable Long Polling When Creating a Queue

This example creates a queue with long polling enabled. If the queue already exists, no error is returned.

Create a new Go file named sqs_longpolling_create_queue.go. You must import the relevant Go and AWS SDK for Go packages by adding the following lines.

Copy
package main import ( "flag" "fmt" "os" "strconv" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sqs" )

Get the queue name passed in by the user.

Copy
func main() { var name string var timeout int flag.StringVar(&name, "n", "", "Queue name") flag.IntVar(&timeout, "t", 20, "(Optional) Timeout in seconds for long polling") flag.Parse() if len(name) == 0 { flag.PrintDefaults() exitErrorf("Queue name required") }

Initialize a session that the SDK will use to load credentials from the shared credentials file, ~/.aws/credentials.

Copy
sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-west-2")}, ) // Create a SQS service client. svc := sqs.New(sess)

Create the queue with long polling enabled. Print any errors or a success message.

Copy
result, err := svc.CreateQueue(&sqs.CreateQueueInput{ QueueName: aws.String(name), Attributes: aws.StringMap(map[string]string{ "ReceiveMessageWaitTimeSeconds": strconv.Itoa(timeout), }), }) if err != nil { exitErrorf("Unable to create queue %q, %v.", name, err) } fmt.Printf("Succesffuly created queue %q. URL: %s\n", name, aws.StringValue(result.QueueUrl)) }

The example uses this utility function.

Copy
func exitErrorf(msg string, args ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", args...) os.Exit(1) }

Enable Long Polling on an Existing Queue

Create a new Go file named sqs_longpolling_existing_queue.go.

You must import the relevant Go and AWS SDK for Go packages by adding the following lines.

Copy
package main import ( "flag" "fmt" "os" "strconv" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sqs" )

This example takes two flags, the -n flag is the queue name, and the -t flag contains the timeout value.

Copy
func main() { var name string var timeout int flag.StringVar(&name, "n", "", "Queue name") flag.IntVar(&timeout, "t", 20, "(Optional) Timeout in seconds for long polling") flag.Parse() if len(name) == 0 { flag.PrintDefaults() exitErrorf("Queue name required") }

Initialize a session that the SDK will use to load credentials from the shared credentials file, ~/.aws/credentials.

Copy
sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-west-2")}, ) // Create a SQS service client. svc := sqs.New(sess)

You need to convert the queue name into a URL. Make the GetQueueUrl API call to retrieve the URL. This is needed for setting attributes on the queue.

Copy
resultURL, err := svc.GetQueueUrl(&sqs.GetQueueUrlInput{ QueueName: aws.String(name), }) if err != nil { if aerr, ok := err.(awserr.Error); ok && aerr.Code() == sqs.ErrCodeQueueDoesNotExist { exitErrorf("Unable to find queue %q.", name) } exitErrorf("Unable to get queue %q, %v.", name, err) }

Update the queue to enable long polling with a call to SetQueueAttributes, passing in the queue URL. Print any errors or a success message.

Copy
_, err = svc.SetQueueAttributes(&sqs.SetQueueAttributesInput{ QueueUrl: resultURL.QueueUrl, Attributes: aws.StringMap(map[string]string{ "ReceiveMessageWaitTimeSeconds": strconv.Itoa(timeout), }), }) if err != nil { exitErrorf("Unable to update queue %q, %v.", name, err) } fmt.Printf("Succesffuly updated queue %q.\n", name) } func exitErrorf(msg string, args ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", args...) os.Exit(1) }

Enable Long Polling on Message Receipt

Create a new Go file named sqs_longpolling_receive_message.go.

You must import the relevant Go and AWS SDK for Go packages by adding the following lines.

Copy
package main import ( "flag" "fmt" "os" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sqs" )

This example takes two flags, the -n flag is the queue name, and the -t flag contains the timeout value.

Copy
func main() { var name string var timeout int64 flag.StringVar(&name, "n", "", "Queue name") flag.Int64Var(&timeout, "t", 20, "(Optional) Timeout in seconds for long polling") flag.Parse() if len(name) == 0 { flag.PrintDefaults() exitErrorf("Queue name required") }

Initialize a session that the SDK will use to load credentials from the shared credentials file, ~/.aws/credentials.

Copy
sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-west-2")}, ) // Create a SQS service client. svc := sqs.New(sess)

You need to convert the queue name into a URL. Make the GetQueueUrl API call to retrieve the URL. This is needed for setting attributes on the queue.

Copy
resultURL, err := svc.GetQueueUrl(&sqs.GetQueueUrlInput{ QueueName: aws.String(name), }) if err != nil { if aerr, ok := err.(awserr.Error); ok && aerr.Code() == sqs.ErrCodeQueueDoesNotExist { exitErrorf("Unable to find queue %q.", name) } exitErrorf("Unable to queue %q, %v.", name, err) }

Receive a message from the queue with long polling enabled with a call to ReceiveMessage, passing in the queue URL. Print any errors or a success message.

Copy
result, err := svc.ReceiveMessage(&sqs.ReceiveMessageInput{ QueueUrl: resultURL.QueueUrl, AttributeNames: aws.StringSlice([]string{ "SentTimestamp", }), MaxNumberOfMessages: aws.Int64(1), MessageAttributeNames: aws.StringSlice([]string{ "All", }), WaitTimeSeconds: aws.Int64(timeout), }) if err != nil { exitErrorf("Unable to receive message from queue %q, %v.", name, err) } fmt.Printf("Received %d messages.\n", len(result.Messages)) if len(result.Messages) > 0 { fmt.Println(result.Messages) } } func exitErrorf(msg string, args ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", args...) os.Exit(1) }