Skip to main content

Context

Overview

Modules should be unaware of the execution context within which they are run, they should have no dependencies on AWS Lambda, Express or any other infrastructure specifics. The intention therefore of the context component is to provide a consistent programming interface that all our business modules use, which creates an abstraction over the execution context.

Context class should be initialised at the start of an API request or event handler in order to provide the context required for the code handler including database session, access to the event bridge, the incoming event information etc.

The Context is the only parameter passed to our API / Event handlers, providing consistency and an easy ability to introduce cross cutting concerns to our code such as logging, error handling etc.

Code Entry Points

The context is initialised in one of three ways, essentially we have 2 different entry points into our module handlers at the moment, these are

  1. API (Koa): We use Koa as a lightweight web server for our APIs, each API service configures an instance of handlers/api.ts. The Api class configures a catch all route for Koa and uses the OpenAPI spec to configure the API routes / security schemas etc. The Api class handles all incoming API calls, initialises the context and database session, and routes the request to the appropriate handler.
  2. Lambda via Eventbridge: The event entry point is defined in the service along with any configuration required for deployment. The entry point passes the request through to the eventhandler in components/context/handlers/event.ts which will set up the context and route the incoming event to the appropriate handler.

You can find how to's for creating new handlers for each entry point type here

Context Properties

  1. Event: A lightweight class which exposes a set of properties used by most modules. The context is initialised in one of two ways, either via the context middleware component (components/context/middleware/context.ts) for APIs or via the generic event handler (components/context/handers/event.ts) for events.
  2. Session: Provides access to the current database session which is scoped per api request or per event.
  3. EventPublisher: Provides access to the AWS event bridge for publishing events
  4. error: If an error occurs during execution it will be stored in this field, any middleware error handlers will be invoked, then the error will be rethrown
  5. props: property bag for any custom data needed for the execution context

Middleware

One advantage of having a consistent programming interface for all our handlers is the ability to inject cross cutting concerns into each handlers execution.

To facilitate this we have a basic port of middy (middy.ts), customised to work with our event and api handler signature.

Each middleware component can export 3 functions

  • before: runs before the base handler executes
  • after: runs after the base handler executes
  • error: runs if any errors occur during handler or middleware execution

Middleware examples can be found in the ./components/context/middleware folder

There are a couple of middlewares

  • context: for managing database session per api or event handler
  • sentry: for logging errors to Sentry and performance monitoring

Each code entry point has the option to configure the generic handlers with additional middleware that may be specific to that event.