5

I'm trying to build an application with a basic client-server infrastructure. The server infrastructure is hosted on AWS, and when a client logs on, it sends a message to the server to set up various infrastructure considerations. One of the pieces of infrastructure is an SQS Queue that the client can poll from to get updates from the server (eventually I'd like to build a push service but I don't know how for right now).

I'm building this application in NodeJS using the Node AWS SDK. The problem I'm having is I need the queue ARN to do various things like subscribe the SQS queue to an SNS topic that the application uses, but the create queue API returns the queue URL, not ARN. So I can get the ARN from the URL using the getQueueAttributes API, but it doesn't seem to be working. Whenever I call it, I get undefined as the response. Here's my code, please tell me what I'm doing wrong:

exports.handler = (event, context, callback) => {

    new aws.SQS({apiVersion: '2012-11-05'}).createQueue({
            QueueName: event.userId
        }).promise()
    )
    .then(data => { /* This has the Queue URL */
        new aws.SQS({apiVersion: '2012-11-05'}).getQueueAttributes({
            QueueUrl: data.QueueUrl,
            AttributeNames: ['QueueArn']
        }).promise()
    })
    .then(data => {
        console.log(JSON.stringify(data)); /* prints "undefined" */
    })
/* Some more code down here that's irrelevant */
}

Thanks!

Ertai87
  • 1,156
  • 1
  • 15
  • 26
  • did you try `All` instead of `QueueArn`, what does it return ? – Ersoy Apr 22 '20 at 21:00
  • I tried 'All', ['All'], ['QueueArn'], and 'QueueArn'. All of those return undefined. – Ertai87 Apr 22 '20 at 21:04
  • did you try to call `getQueueAttributes` on an existing queue- i mean if aws is creating the queue async then you may not get it back even the `createQueue` is completed. – Ersoy Apr 22 '20 at 21:15
  • Yup, I tried creating the queue and then commenting out the create queue part and hardocding in the queue URL from the AWS console. That didn't work either. By the way, because it's probably going to be your next question, I did try using AWS CLI from console and it worked perfectly. – Ertai87 Apr 22 '20 at 21:24
  • yes :) - what about the execution role of this lambda - does this lambda's role allowed to access SQS ? – Ersoy Apr 22 '20 at 21:32
  • since you are creating queue, you probably have full access, but maybe in the policies something missing to read. – Ersoy Apr 22 '20 at 21:34
  • I just attached the default AWS SQS Full Access role to my lambda execution role. – Ertai87 Apr 22 '20 at 21:35
  • i managed to try on my aws console and received arn successfully - i will share the code as answer for formatting and size – Ersoy Apr 22 '20 at 21:41
  • I'm doing the exact same thing you are, and falling into the exact same issues. Why AWS doesn't provide the ARN on queue creation is the real question. Does AWS not have a suggestion place or a bug reporting area? I'll gladly go and document this issue/bug. – Jeach Nov 04 '22 at 19:40

2 Answers2

11
const AWS = require('aws-sdk');
const sqs = new AWS.SQS();

exports.handler = async(event, context, callback) => {

    var params = {
        QueueUrl: 'my-queue-url',
        AttributeNames: ['QueueArn']
    };

    let fo = await sqs.getQueueAttributes(params).promise();
    console.log(fo);
};

and it printed

{
    ResponseMetadata: { RequestId: '123456-1234-1234-1234-12345' },
    Attributes: {
        QueueArn: 'arn:aws:sqs:eu-west-1:12345:my-queue-name'
    }
}
Ersoy
  • 8,816
  • 6
  • 34
  • 48
  • Lambda console (partial output): "errorMessage": "SyntaxError: await is only valid in async function", – Ertai87 Apr 22 '20 at 22:25
  • please check > exports.handler = `async`(event, context, callback) => { – Ersoy Apr 22 '20 at 22:27
  • When I changed the await to a Promise.then() then it worked. I've spent too much time on this today, I'll try to expand on this tomorrow and get back to you. Did you try chaining promises in the way that I am trying to do it, by creating the queue and then trying to read from it? I'm going to try that tomorrow when I come back to this. – Ertai87 Apr 22 '20 at 22:29
  • didn't try, just tried to receive it with the current code. you may use async/await inside lambda which may save you from callbacks. AFAIK almost all aws-sdk library methods support async/await. – Ersoy Apr 22 '20 at 22:32
  • OK, if I make my function async and then I split my Promise.then chain into a bunch of await calls then it works. I would be interested in some insight as to why this is (I'm kind of a beginner at NodeJS so I don't understand it). – Ertai87 Apr 22 '20 at 22:43
  • Please check https://stackoverflow.com/a/34401662/2188922 and https://medium.com/front-end-weekly/callbacks-promises-and-async-await-ad4756e01d90 (i am not the author of both posts, they explain well) – Ersoy Apr 22 '20 at 22:47
  • Upvoted the answer for all your help, but this wasn't actually the answer. I posted the answer myself. – Ertai87 Apr 23 '20 at 17:44
1

With the help of Ersoy, I realized that I was using block-formatting (with {}) to write my Promises, but I was never returning anything from those blocks. I had thought that the last value in the Promise block was the return value by default, but it seems that was not the case. When I added return before the SQS API command, then it worked (without using async/await).

Ertai87
  • 1,156
  • 1
  • 15
  • 26