apex / apex-go

Golang runtime for Apex/Lambda.
MIT License
293 stars 32 forks source link

Golang Process exited before completing request when connecting to RDS Mysql DB #55

Open prakashsanker opened 7 years ago

prakashsanker commented 7 years ago

Hey,

So I'm connecting to a RDS Mysql DB using golang's sql driver.

I do so like this

func main() {
  db, err := sql.Open("mysql", "db_details")
  err = db.Ping()
  if err != nil {
    fmt.Println("Failed to prepare connection to database")
    // log.Fatal("Error:", err.Error())
  }
    apex.HandleFunc(func(event json.RawMessage, ctx *apex.Context) (interface{}, error) {
      fmt.Println(ctx)
      return map[string]string{"hello": "world"}, nil
    })
}

The function is called getTags and I get this error when I do apex invoke getTags

Process exited before completing request

This doesn't look like a run time error, as a Println put right before the sql.Open doesn't run.

From looking around, most of the examples are in node and indicate that I need to do a context.done or raise the timeout.

I increased the timeout to 300s and the same error occurred.

I then looked around the source code to see if the Context type had a Done function defined on it...but it doesn't look like it does.

I looked at the logs and found this

/aws/lambda/chanakya-serverless-api_getTags panic: runtime error: invalid memory address or nil pointer dereference
/aws/lambda/chanakya-serverless-api_getTags [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x47b8ba]
/aws/lambda/chanakya-serverless-api_getTags 
goroutine 1 [running]:
/aws/lambda/chanakya-serverless-api_getTags panic(0x4d9780, 0xc42000a030)
/aws/lambda/chanakya-serverless-api_getTags     /Users/psanker/.gvm/gos/go1.7/src/runtime/panic.go:500 +0x1a1
/aws/lambda/chanakya-serverless-api_getTags database/sql.(*DB).conn(0x0, 0x4cfd01, 0xc42000a340, 0x4f5cef, 0x5)
/aws/lambda/chanakya-serverless-api_getTags     /Users/psanker/.gvm/gos/go1.7/src/database/sql/sql.go:781 +0x3a
/aws/lambda/chanakya-serverless-api_getTags database/sql.(*DB).Ping(0x0, 0x5, 0x4fd4c0)
/aws/lambda/chanakya-serverless-api_getTags     /Users/psanker/.gvm/gos/go1.7/src/database/sql/sql.go:503 +0x34
/aws/lambda/chanakya-serverless-api_getTags main.main()
/aws/lambda/chanakya-serverless-api_getTags     /Users/psanker/chanakya-serverless-api/functions/getTags/main.go:13 +0xe6

So I then went to a non-apex version of the code (I'm porting a codebase over) and tried the same code...and everything worked, so I'm not sure why there is a segfault.

What is the way around this? Why is this happening?

polds commented 7 years ago

Potentially a couple of things going on here. First fmt.Println() writes to Stdout which Apex can't do. You need to write to Stderr (fmt.Fprintf(os.Stderr, "message")).

Second your first err isn't being handled:

db, err := sql.Open("mysql", "db_details")
err = db.Ping()

Additionally, you may have some issues dropping the context into that Println. I've seen issues where Apex doesn't always like to log out pointers. A potential solution is to do something like fmt.Fprintf(os.Stderr, "%#v\n", ctx)

Finally to answer your question about raising a context.done, simply by returning from the func the node shim will raise the .done on your behalf.