11
votes

I'm trying to publish some data to SNS from a Lambda function call, but it doesn't seem to be working. My function code is -

public class Handler implements RequestHandler<DynamodbEvent, Void> {

    private static final String SNS_TOPIC_ARN = "arn:aws:sns:us-west-2:account_number:function_name";

    @Override
    public Void handleRequest(DynamodbEvent dynamodbEvent, Context context) {

        LambdaLogger logger = context.getLogger();

        AmazonSNSClient snsClient = new AmazonSNSClient(new DefaultAWSCredentialsProviderChain());
        snsClient.setRegion(Region.getRegion(Regions.US_WEST_2));

        for (DynamodbStreamRecord record : dynamodbEvent.getRecords()) {
            Map<String, AttributeValue> newImage = record.getDynamodb().getNewImage();

            if (newImage == null) {
                continue;
            }

            String sensorId = newImage.get("sensorID").getS();
            long timestamp = Long.parseLong(newImage.get("timestamp").getS());
            double temperature = Double.parseDouble(newImage.get("payload").getM().get("temp").getN());

            String data = sensorId + " " + timestamp + " " + temperature;

            logger.log(data);

            PublishRequest publishRequest = new PublishRequest(SNS_TOPIC_ARN, data);

            PublishResult publishResult = snsClient.publish(publishRequest);

            logger.log("Publish Successful " + publishResult.getMessageId());
        }

        snsClient.shutdown();

        return null;
    }
}

This call results in a timeout (10 seconds) and the lambda invocation fails. If I comment out the SNS publishing part, i.e., if I just log the data received from DynamoDB, it works just fine. As soon as the SNS publishing code is added, it times out.

The timeout message logged in CloudWatch is -

START RequestId: 8db74187-459b-42c5-8a06-b3a74873b236 Version: $LATEST END RequestId: 8db74187-459b-42c5-8a06-b3a74873b236 REPORT RequestId: 8db74187-459b-42c5-8a06-b3a74873b236 Duration: 10001.66 ms Billed Duration: 10000 ms Memory Size: 128 MB Max Memory Used: 37 MB Task timed out after 10.00 seconds

I have all the proper permissions in place, and I'm able to publish to SNS using just the following code running on my PC -

PublishRequest publishRequest = new PublishRequest(SNS_TOPIC_ARN, data);
PublishResult publishResult = snsClient.publish(publishRequest);
System.out.println("Publish Successful " + publishResult.getMessageId());

I have also tried using AmazonSNSAsyncClient instead of AmazonSNSClient, it gives the same result.

What am I missing here ?

3
Try increasing the allocated memory setting to the max. This will speed up the processing necessary to perform the SNS API calls. You currently have it at the slowest setting. Then try increasing the timeout seconds. How many DynamoDB events are you receiving in each AWS Lambda function invocation that times out? - Eric Hammond
@EricHammond I'm receiving just 1 event per lambda call. I doubt that requires more memory and time. The payload is also very tiny. Also, when I add the SNS part, even the first call to logger.log() (the one that logs the received data) is not reached. - Rohan
Java functions are definitely slower to start and need more memory on Lambda than NodeJS or Python functions. I would definitely start by increasing the timeout and available memory. - Mark B
The timeout could also be caused by the fact that requests using the AWS SDK fail they are automatically retried using exponential backoff. This could be happening if there resource doesn't exist, there is a permission issue, or the service is actually down. Set the Lambda function timeout to over a minute or change the SDKs retry logic to avoid this type of timeout altogether. - JaredHatfield
Seems like it was a memory issue after all. Thanks guys. Can one of you post it as an answer ? - Rohan

3 Answers

10
votes

Well, since none of the people who commented on my question are answering, I'll answer it myself.

Increasing the memory usage to 256 MB and timeout to 30 seconds seems to have solved the issue.

2
votes

Increase the amount of memory allocated for the Lambda operation.

0
votes

Increasing the memory allocated to the lambda function worked for me as well (this setting is in the lambda console under basic settings).

This one was maddening for me - I was using the same JAR file for 2 different lambda functions with identical configurations, and the SNS call was working for one but timing out for the other. Maddening!