3

I am trying to do basic db connection in AWS Lambda with Go, and for some reason, it got stuck at db.prepare() and no log is presented in cloudwatch.

func Handler(request Request) (Response, error) {

    db, err := sql.Open("mysql", dbUsername+":"+dbPassword+"@tcp("+dbURL+":"+dbPort+")/"+dbName)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    stmt, err := db.Prepare("SELECT id, password FROM package_passwords WHERE password = ?")
    return Response{
        Message: "rows",
        Ok:      false,
    }, nil
}

weird thing is that the code above stuck at least more than 5 second in AWS Lambda while it works fine in plain go run/ go build.

Talenel
  • 422
  • 2
  • 6
  • 25
Thomas Kao
  • 49
  • 1
  • 6
  • This is not answering your question, but: Are you saving the passwords in plain text in the database? – mbuechmann Jun 26 '18 at 07:43
  • yes, it is stored as plan text. and the same go syntax works in plain go build but not in AWS Lambda – Thomas Kao Jun 26 '18 at 07:49
  • This is, again, not about your original question. But I would urgently advise you to use password encryption. – mbuechmann Jun 26 '18 at 07:51
  • Thanks for the advice! It is actually bad naming as the purpose of those base32 text are for redeem something, and those should be named as redeem codes or something. – Thomas Kao Jun 26 '18 at 07:54
  • Ah, ok. Then these are just tokens. Makes sense. – mbuechmann Jun 26 '18 at 08:00
  • i'm not a developer, i don't know how go works, but,just a simple question, is it normal to close the connection before execute the query? – Gianmarco Carrieri Jun 26 '18 at 08:53
  • not common, but in go's case, It is idiomatic to defer db.Close() if the sql.DB should not have a lifetime beyond the scope of the function. – Thomas Kao Jun 26 '18 at 08:59
  • @GianmarcoCarrieri in Go, `defer` will make a function wait until the surrounding function returns before executing it, so in this case `db.Close()` is the last thing that is called. – Marco Bonelli Jun 26 '18 at 09:43
  • Is your db within a vpc? If so, you need to enable vpc access for your lambda function to have access to the instance. However, I suppose it would fail opening the connection and not at the prepare statement. – Nathan Phetteplace Jun 26 '18 at 13:47
  • but should db.Close() be even there. Since that will keep opening and closing connections each time the lambda is called. Wouldn't it? – Vallie Jan 31 '20 at 11:41

2 Answers2

2

It's probably the AWS security groups

The lambda tries to connect but the security groups time it out as they block it forever

Attach the AWSLambdaVPCAccessExecutionRole policy to your lambda and ensure the Lambda is in a VPC. Check the database security groups allow access from the VPC

There are some more pointers in this question Allow AWS Lambda to access RDS Database

Vorsprung
  • 32,923
  • 5
  • 39
  • 63
  • Thanks. VPC is exact the reason that Lambda get blocked and no log in Lambda side. Since I was still coding, I put Lambda function in my Default VPC. On the other hand, the RDS was prepared and put in specific VPC. After adding my function into that db's VPC, it works fine. – Thomas Kao Jun 27 '18 at 09:31
  • glad to hear it. Hope this helps other people to avoid this problem! – Vorsprung Jun 27 '18 at 09:51
0

If it is a RDS operation, I think it is getting timeout. The default timeout of a lambda function is 6 seconds and therefore it is getting timeout before the operation finishes with RDS. To avoid this you do not have to increase the timeout. Instead of that you can make "callBackWaitsForEmptyEventLoop" false as your first line of code in lambda function.

SamPiy93
  • 490
  • 3
  • 13