Camilo Ortúzar
Camilo Ortúzar

Reputation: 49

why my lambda .net api doesnt work with dynamoDb?

i have a problem, when i run the api in my local works fine and do all in the Dynamo db but when i publish to my AWS lambda it doesn't work is there something im missing (the api return status 500)?

the fact is that the code works fine in my premises, the data is inserted correctly, but when I publish it in aws lambda, the crud does not work and it simply does nothing (returns state 500), will there be any permission missing?

the code freezes in this line:

        Table table = Table.LoadTable(client_, "TblUsers_");

the code is here:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Threading.Tasks;
using System.Linq;
using System.Transactions;
using UserCrudApiChallenge.Infraestructure.Interface;
using UserCrudApiChallenge.CrossCutting.User;
using UserCrudApiChallenge.Domain.Entity;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon;
using Amazon.S3;

namespace UserCrudApiChallenge.Infraestructure.Repository
{
    public class UserRepository : IUserRepository
    {
        private readonly BasicAWSCredentials _connection;

        public UserRepository()
        {
            _connection =  new  BasicAWSCredentials(Environment.GetEnvironmentVariable("DYNAMODB_ACCESS_KEY"),
                Environment.GetEnvironmentVariable("DYNAMODB_SECRET_KEY"));    
        }

        public async Task<User> AddUserAsync(User user)
        {
            try
            {
                AmazonDynamoDBClient client_ = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);
                Table table = Table.LoadTable(client_, "TblUsers_");
                DynamoDBContext context = new DynamoDBContext(client_);
                Document result = await table.PutItemAsync(context.ToDocument(user));

                return user;
            }
            catch (Exception ex)
            {
                Console.WriteLine("FAILED to write the new user, because:\n       {0}.", ex.Message);
                throw;
            }            
        }

        public async Task<bool> UpdateUserAsync(User user)
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);
                UpdateItemRequest updateRequest = new UpdateItemRequest()
                {
                    TableName = "TblUsers_",
                    Key = new Dictionary<string, AttributeValue>
                {
                    {"Id", new AttributeValue {S = user.Id } }
                },
                    AttributeUpdates = new Dictionary<string, AttributeValueUpdate>
                {
                        {"Name", new AttributeValueUpdate
                        {
                            Value = new AttributeValue{ S =  user.Name },
                            Action = AttributeAction.PUT
                        }
                    },
                    {"Email", new AttributeValueUpdate
                        {
                            Value = new AttributeValue{ S =  user.Email },
                            Action = AttributeAction.PUT
                        }
                    },
                     {"Password", new AttributeValueUpdate
                        {
                            Value = new AttributeValue{ S =  user.Password },
                            Action = AttributeAction.PUT
                        }
                    }
                }
                };
                await client.UpdateItemAsync(updateRequest);

                return true;
            }
            catch (Exception ex)
            {  
                throw;
            }         
        }

        public async Task<User> FindUserByIdAsync(string userId)
        {    
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);
                Table table = Table.LoadTable(client, "TblUsers_");
                Document result = await table.GetItemAsync(userId);
                return MapUserWithPassword(result);
            }
            catch (Exception ex)
            {  
                throw;
            }
        }

        public async Task<User> FindUserById(string id)
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);

                QueryRequest qry = new QueryRequest
                {
                    TableName = "TblUsers_",
                    ExpressionAttributeNames = new Dictionary<string, string>
                    {
                      { "#Id", "Id" }
                    },
                    ExpressionAttributeValues = new Dictionary<string, AttributeValue> { { ":id", new AttributeValue { S = id } } },
                    KeyConditionExpression = "#Id = :id",
                };

                var result = await client.QueryAsync(qry);

                if (result.Count == 0 || result is null)
                {
                    throw new Exception("No user");
                }
    
                return UsersMapper(result.Items.FirstOrDefault());
            }
            catch (Exception ex)
            {    
                throw;
            }   
        }

        public async Task<List<User>> GetUsers()
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);

                DynamoDBContext context = new DynamoDBContext(client);
                Table table = Table.LoadTable(client, "TblUsers_");

                //get all records
                var conditions = new List<ScanCondition>();
                // you can add scan conditions, or leave empty
                List<User> allUsers = await context.ScanAsync<User>(conditions).GetRemainingAsync();
                return allUsers;
            }
            catch (Exception ex)
            {    
                throw;
            }    
        }

        public async Task<bool> DeleteUserAsync(string id)
        {
            try
            {
                AmazonDynamoDBClient client = new AmazonDynamoDBClient(_connection, RegionEndpoint.USEast2);

                DeleteItemRequest request = new DeleteItemRequest
                {
                    TableName = "TblUsers_",
                    Key = new Dictionary<string, AttributeValue> { { "Id", new AttributeValue { S = id } } }
                };

                await client.DeleteItemAsync(request);

                return true;
            }
            catch (Exception ex)
            {    
                throw;
            }           
        }    

        private User MapUserWithPassword(Document document)
        {
            User user = new User(document["Id"], document["Name"], string.Empty, document["Email"]);
            return user;
        }

        private User UsersMapper(Dictionary<string, AttributeValue> item)
        {    
            try
            {
                User user = new User(item["Id"].S, item["Name"].S, item["Password"].S, item["Email"].S);

                return user;
            }
            catch (Exception ex)
            {   
                throw;
            }
        }
    }
}

Upvotes: 0

Views: 221

Answers (1)

John Rotenstein
John Rotenstein

Reputation: 270184

DynamoDB is a service that is accessed via the Internet. Therefore, if your AWS Lambda function cannot access the Internet, it might not be reaching DynamoDB.

When an AWS Lambda function is configured to use a VPC, it can only access DynamoDB if:

  • The Lambda function is connected to a private subnet and there is a NAT Gateway in a public subnet, OR
  • The VPC has been configured with a VPC endpoint for DynamoDB, which directly connects the VPC to DynamoDB

If the Lambda function does not require VPC access, then disconnect the Lambda function from the VPC. This will automatically provide Internet access.

Upvotes: 1

Related Questions