Skip to content

Commit

Permalink
Add support for type-safe Start* function (#468)
Browse files Browse the repository at this point in the history
* add HandlerFunc interface and StartWithOptionsTypeSafe

* add tests for StartWithOptionsTypeSafe

* Update test to cover bool from validateArguments

* move generic code to dedicated files with build tag

* Reduce HandlerFunc interface to just one variant. Rename StartWithOptionsTypeSafe to StartHandlerFunc

* add ValidateHandlerFunc

* Revert "add ValidateHandlerFunc"

This reverts commit bc1e02e.

* add context-arg-only reflections back to the godoc

* update copyright date in new file to match year of file's creation

* update copyright year in new test file to match the year of file's creation

Co-authored-by: Bryan Moffatt <[email protected]>
  • Loading branch information
logandavies181 and bmoffatt authored Dec 4, 2022
1 parent 666b0d8 commit 858a4cf
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
9 changes: 6 additions & 3 deletions lambda/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,23 @@ import (
// - handler must be a function
// - handler may take between 0 and two arguments.
// - if there are two arguments, the first argument must satisfy the "context.Context" interface.
// - handler may return between 0 and two arguments.
// - if there are two return values, the second argument must be an error.
// - handler may return between 0 and two values.
// - if there are two return values, the second return value must be an error.
// - if there is one return value it must be an error.
//
// Valid function signatures:
//
// func ()
// func (TIn)
// func () error
// func (TIn) error
// func () (TOut, error)
// func (TIn) (TOut, error)
// func (context.Context)
// func (context.Context) error
// func (context.Context, TIn) error
// func (context.Context) (TOut, error)
// func (context.Context, TIn)
// func (context.Context, TIn) error
// func (context.Context, TIn) (TOut, error)
//
// Where "TIn" and "TOut" are types compatible with the "encoding/json" standard library.
Expand Down
23 changes: 23 additions & 0 deletions lambda/entry_generic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build go1.18
// +build go1.18

// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved

package lambda

import (
"context"
)

// HandlerFunc represents a valid input with two arguments and two returns as described by Start
type HandlerFunc[TIn, TOut any] interface {
func(context.Context, TIn) (TOut, error)
}

// StartHandlerFunc is the same as StartWithOptions except that it takes a generic input
// so that the function signature can be validated at compile time.
//
// Currently only the `func (context.Context, TIn) (TOut, error)` variant is supported
func StartHandlerFunc[TIn any, TOut any, H HandlerFunc[TIn, TOut]](handler H, options ...Option) {
start(newHandler(handler, options...))
}
36 changes: 36 additions & 0 deletions lambda/entry_generic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build go1.18
// +build go1.18

// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved

package lambda

import (
"context"
"fmt"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
)

func TestStartHandlerFunc(t *testing.T) {
actual := "unexpected"
logFatalf = func(format string, v ...interface{}) {
actual = fmt.Sprintf(format, v...)
}

f := func(context.Context, any) (any, error) { return 1, nil }
StartHandlerFunc(f)

assert.Equal(t, "expected AWS Lambda environment variables [_LAMBDA_SERVER_PORT AWS_LAMBDA_RUNTIME_API] are not defined", actual)

handlerType := reflect.TypeOf(f)

handlerTakesContext, err := validateArguments(handlerType)
assert.NoError(t, err)
assert.True(t, handlerTakesContext)

err = validateReturns(handlerType)
assert.NoError(t, err)
}

0 comments on commit 858a4cf

Please sign in to comment.