Bob Hinchliffe
Bob Hinchliffe

Reputation: 78

Retrieve the SQS Queue URL dynamically from the lambda event or context

I have a single lambda function which responds to two different SQS queues invoking it (the second one is a back-off queue) and so I want to dynamically determine which queue the message came from, so that I can remove it once it has been processed.

I am able to create the EventSourceMapping to trigger the lambda from both queues, but I cannot see how I cleanly retrieve the QueueURL I need in order to perform a DeleteMessage call. I am using the AWS Golang SDK.

There is the EventSourceArn in the body of the event messages and it seems I could use GetQueueURL but that would be an additional API call.

The only way to avoid that (I can think of) is to pass both queue URLs in as environment variables and use the queue name from EventSourceArn to find it.

Is there a better way that this? Is there something hiding in the context that isn't documented?

Upvotes: 2

Views: 2536

Answers (2)

George Richardson
George Richardson

Reputation: 1268

You can rebuild the queue URL from its ARN which you have in the event as EventSourceARN.

package main

import (
    "context"
    "fmt"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws/arn"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/sqs"
)

var client *sqs.SQS

func main() {
  client = sqs.New(session.Must(session.NewSessionWithOptions(session.Options{
        SharedConfigState: session.SharedConfigEnable,
    })))
    lambda.Start(Handle)
}

func Handle(ctx context.Context, event events.SQSEvent) {  
    for _, record := range event.Records {
        // Process message
        fmt.Printf(record.Body)

        // Rebuild Queue URL from ARN 
        queueArn, _ := arn.Parse(record.EventSourceARN)
        queueUrl := fmt.Sprintf("https://sqs.%v.amazonaws.com/%v/%v", queueArn.Region, queueArn.AccountID, queueArn.Resource)

        // Delete message from queue
        client.DeleteMessage(&sqs.DeleteMessageInput{
            QueueUrl:      &queueUrl,
            ReceiptHandle: &record.ReceiptHandle,
        })
    }
}

If you are using a non-standard AWS partition (e.g. China) you will also need to change the root domain of the URL to match.

Upvotes: 2

aherve
aherve

Reputation: 4060

If you are using lambda, SQS and an event-source-mapping, then you don't have to manually delete objects from sqs: When your function successfully processes a batch, Lambda deletes its messages from the queue

Just return a success code, and the message will automatically be deleted from the relevant SQS queue

Upvotes: 1

Related Questions