Package Structure

Package structure and operating method

This vignette provides an overview of how the package is structures and how the functions are used. It is intended for package developers and contributors.

Runtime endpoints

The runtime works by querying HTTP endpoints configured by AWS Lambda. These endpoints are determined by on the “AWS_LAMBDA_RUNTIME_API” environment variable set by AWS Lambda during initialisation. They generally won’t be available locally.

The next invocation and initialisation error endpoints are unique in each Lambda instance. The response and invocation error endpoints are determined by the request_id associated with each invocation. The request ID is given in the “lambda-runtime-aws-request-id” header in the response to the query to the next invocation endpoint.

Handler functions

Every Lambda instance is centred around a single function which handles any inputs. The handler function is determined by an environment variable which can be configured in one of two ways:

The lambda_config function (run as part of start_lambda) picks up on this environment variable and identifies the R function to which it refers. This handler function is used to process all invocations.

Event classification according to invocation

Events need to be handled differently depending upon whether they are invoked directly, by an API Gateway, etc. Events are classified according to their detected invocation method, with their invocation stored as an S3 class. The following functions dispatch on this class:

Event listening lifecycle

The main function — start_lambda — accepts an optional configuration provided by lambda_config. The default configuration should suffice if the handler is configured in either the Dockerfile or the AWS Lambda console. It will then run the internal start_listening function.

The start_listening function will augment the configuration with context extracted from the environment (using the extract_context_from_environment function). It will then set up an infinite loop that listens for invocations, interprets them as events, and processes them with the handler function.

Specifically, start_listening triggers the listening loop, which consists of wait_for_event and handle_event (combined into wait_for_and_handle_event). Once a response (called an invocation) is sent to the request made in wait_for_event, it is decomposed into an event, and classified according to its (detected) invocation type.

If an error occurs during this stage it is handled by handle_decomposition_error. If possible the error will be posted to the error invocation endpoint so that Lambda can process it, but otherwise it will simply be logged and then the runtime will move onto the next invocation.

The event is passed to handle_event which consists of the following steps:

Afterwards, the runtime will return to the wait_for_event function and process the next invocation that arrives. AWS Lambda may shut down the instance if it times out before another event invocation arrives.

Alternatively, if an error occurs during wait_for_event it will be handled by handle_decomposition_error, or if it occurs during handle_event it will be dispatched to the appropriate handle_event_error method according to the S3 class of the event. In either case this will not stop the R session — an error when processing a single event is a problem for that event alone. The runtime will return to the wait_for_event step.

All of these functions are diagrammed below, with boxes representing functions which are grouped together according to the primary function that calls each of them in sequence. Errors are shown in red.