lambdawrap

package module
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2022 License: Apache-2.0 Imports: 6 Imported by: 0

README

lambdawrap

license standard-readme compliant Actions Status

A set of composable functions to reduce the repeated code required to implement AWS lambdas.

Table of Contents

Background

Writing AWS Lambdas often require common tasks, such as unmarshalling SNS messages and then unmarshalling an inner SQS message. This kind of code still requires testing in each individual lambda. This library attempts to remove that repeated complexity, as well as other useful utility functions.

Install

This library makes use of Go generics, as such it is only compatible with Go >= 1.18!

go get github.com/pwood/lambdawrap

Usage

This library is under active development, it should not be used in production.

Please note that tests for the different wraps will often include generic typing information, this is usually not required in production use, as Go can infer the typing information when used in place.

Maintainers

@pwood

Contributing

Feel free to dive in! Open an issue or submit PRs.

This project follows the Contributor Covenant Code of Conduct.

License

Copyright 2022 Peter Wood & Contributors

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an " AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DomainObject

func DomainObject[I any, O any](n func(context.Context, I) (O, error), c Codec) func(context.Context, []byte) ([]byte, error)

DomainObject provides an automated approach to unmarshalling an input domain object, and then automatically marshalling the output domain object. For processes that are side effect only (i.e. no output type), see SideEffect to mask the return type, otherwise ensure the that first return value of n is nil.

func DynamoDBStream

func DynamoDBStream(n func(context.Context, events.DynamoDBEventRecord) ([]byte, error)) func(context.Context, events.DynamoDBEvent) ([]byte, error)

DynamoDBStream provides a wrapper to iterate through multiple events.DynamoDBEvent. Default behaviour is to concatenate the []byte output from each message, returning to the caller.

func Err

func Err[O any](e error) func(context.Context, O) ([]byte, error)

Err is a construct to return an empty error response.

func Filter

func Filter[O any](f func(context.Context, O) (bool, error), n func(context.Context, O) ([]byte, error)) func(context.Context, O) ([]byte, error)

Filter is a generic component that can be added to most wrapper chains, it calls the user provided function for each object passed in the chain. That function should return true if the message should be processed further, false if processing should go no further, or raise an error if a problem occurs.

An example might be S3 notification processing:

myS3Filter := func(_ context.Context, s3Not events.S3EventRecord) (bool, error) {
  return (s3Not.EventName == "s3:ObjectCreated:Put"), nil
}

myS3Consumer := func(_ context.Context, fileContents []byte) ([]byte, error) {
  return fileContents, nil
}

wrap := SQS(S3Notification(Filter(myS3Filter, S3Fetch(RealAll(myS3Consumer)))))

func Match

func Match[O any](f func(context.Context, O) (bool, error), m func(context.Context, O) ([]byte, error), n func(context.Context, O) ([]byte, error)) func(context.Context, O) ([]byte, error)

Match is similar to Filter, however it permits handling the failing case with a different function, n. This permits the code path to diverge based upon the match result. This can be useful with guardrail filters that should error if the filter fails a match.

func Nop

func Nop[O any]() func(context.Context, O) ([]byte, error)

Nop is a construct to do nothing further to an event, and return an empty non error response.

func Output

func Output[O any](n func(context.Context, O) ([]byte, error), ofn func(context.Context, []byte) error) func(context.Context, O) ([]byte, error)

Output is used to capture the result of the next, pass it to another function and then discard the data. This is useful for the output of DomainObject when the source has multiple records (and thus multiple next invocations), such as SQS, SNS, DynamoDBStream or S3Notification.

func S3EntityFromContext added in v0.2.1

func S3EntityFromContext(ctx context.Context) (events.S3Entity, bool)

S3EntityFromContext retrieves an events.S3Entity from the context, for use after an S3Fetch wrap has been used if the application needs the events.S3Entity that was downloaded.

func S3Fetch

func S3Fetch(n func(context.Context, io.Reader) ([]byte, error), i S3Fetcher) func(context.Context, events.S3EventRecord) ([]byte, error)

S3Fetch consumes an events.S3EventRecord and retrieves the object from S3, providing an io.Reader to the next function. Default behaviour is to concatenate the []byte output from each message, returning to the caller.

The actual network code to fetch an S3 object is provided to the function via i, a function that implements the S3Fetcher interface. This may make this function seem very light, however it is done so due to the complexities surrounding constructing S3 clients and the infinite combinations of configuration that might be needed.

A copy of the event.S3Entity is added to the context, and can be extracted with S3EntityFromContext.

A very basic S3 Fetcher implementation is included as impl.Fetcher, it is a submodule so will need to be imported separately, this is to prevent the dependency of the AWS SDK leaking into lambdawrap.

func S3Notification

func S3Notification(n func(context.Context, events.S3EventRecord) ([]byte, error)) func(context.Context, events.S3Event) ([]byte, error)

S3Notification provides a wrapper to iterate through multiple S3 records included in an events.S3Event. Default behaviour is to concatenate the []byte output from each message, returning to the caller.

func S3ReadAll added in v0.2.0

func S3ReadAll(n func(context.Context, []byte) ([]byte, error)) func(context.Context, io.Reader) ([]byte, error)

S3ReadAll consumes an io.Reader and provides a []byte to the next function. Default behaviour is to concatenate the []byte output from each message, returning to the caller.

func SNS

func SNS[O any](n func(context.Context, O) ([]byte, error)) func(context.Context, events.SNSEvent) ([]byte, error)

SNS provides a wrapper to iterate through multiple SNS records included in an events.SNSEvent. Default behaviour is to concatenate the []byte output from each message, returning to the caller.

SNS will attempt to unmarshal any destination structure with JSON, this is implemented for chaining wraps (e.g. SNS(SQS(S3Notification()))). It is recommended you use DomainObject instead, a Codec can be provided to support encodings other than JSON.

Do not use this directly for domain objects, use DomainObject.

func SNSTopicARNFromContext added in v0.2.3

func SNSTopicARNFromContext(ctx context.Context) (string, bool)

SNSTopicARNFromContext retrieves a SNS topic ARN from the context, for use after an SNS wrap has been used if the application needs the topic that the message was provided on.

func SQS

func SQS[O any](n func(context.Context, O) ([]byte, error)) func(context.Context, events.SQSEvent) ([]byte, error)

SQS provides a wrapper to iterate through multiple SQS records included in an events.SQSEvent. Default behaviour is to concatenate the []byte output from each message, returning to the caller.

SQS will attempt to unmarshal any destination structure with JSON, this is implemented for chaining wraps (e.g. SNS(SQS(S3Notification()))). It is recommended you use DomainObject instead, a Codec can be provided to support encodings other than JSON.

Do not use this directly for domain objects, use DomainObject.

func SQSTopicARNFromContext added in v0.2.3

func SQSTopicARNFromContext(ctx context.Context) (string, bool)

SQSTopicARNFromContext retrieves a SQS queue ARN from the context, for use after an SQS wrap has been used if the application needs the topic that the message was provided on.

func SideEffect

func SideEffect[I any](n func(context.Context, I) error) func(context.Context, I) ([]byte, error)

SideEffect provides a way to ignore the requirement of DomainObject to return an output domain object. It is unlikely another function in lambdawrap would then be passed into SideEffect.

Example:

type domainInput struct {}

myFunc := func(ctx context.Context, in domainInput) error

DomainObject(SideEffect(myFunc))

func Switch added in v0.2.2

func Switch[O any, I comparable](f func(O) I, m map[I]func(context.Context, O) ([]byte, error)) func(context.Context, O) ([]byte, error)

Switch allows switching logic to occur based upon a function provided, switching out different downstream behaviour. An example use case might be to change handler based upon an S3 event name.

Types

type Codec

type Codec interface {
	// Marshal processes v and encodes into a []byte
	Marshal(v any) ([]byte, error)
	// Unmarshal processes the data, and decodes back into v
	Unmarshal(data []byte, v any) error
}

Codec defines an interface that can be used to Marshal and Unmarshal different encodings back into Go structures.

See codec.JSON and codec.YAML.

type S3Fetcher

type S3Fetcher func(context.Context, events.S3Entity) (io.ReadCloser, error)

Directories

Path Synopsis
impl module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL