How Swift Code Runs on AWS Lambda
The Serverless Lambda Runtime API
A Swift binary doesn’t just run on AWS Lambda without some help. In comes the Swift AWS Lambda Runtime to abstract away all the complex interactions between the Lamba Runtime API and your code. It was designed to make building Lambda functions in Swift simple and safe. But what exactly is it? What does it do?
AWS Lambda
AWS Lambda is wonderful as a compute service that runs your code in response to events. You do not have to even think about managing the underlying servers that you use. But to get all this to work, your code needs to play by some rules. To work, you agree to adhere to the AWS Lambda Runtime API, and AWS agrees to let you run serverless and ignore maintenance.
AWS maintains prebuilt Runtime API implementations for some programming languages such as Javascript, Python and Go. In an effort to open the platform to all takers — they published their Runtime API allowing any language to run as a Lambda. As such the Swift community has built the Swift AWS Lambda Runtime — an implementation of that API allowing your Swift code to run on AWS Lambda.
AWS Lambda Runtime API
The Lambda Service is an implemation of the APIs for Runtime, Extensions and Logs (3 endpoints). These endpoints combine to make up the execution environment. For this article we are only going to dive into the Runtime API here. Currently it is the only section of the execution environment that is currently implemented by Swift AWS Lambda Runtime.
The runtime is a essentially a part of the program that is responsible for managing the interaction between the Lambda Service and your code. The runtime is responsible for running the function’s setup code, reading the handler name from an environment variable, and reading invocation events from the Lambda runtime API. It runs a Lambda function’s handler method when the function is invoked and passes the event data to the function handler. Any response from the handler is posted back to the Lambda Service.
With this API there is a clear separation of roles and responsibilities. Eg: where your Swift code runs is highlighted in red in the image above (Runtime + Function) and it just needs to know how to talk to the Runtime API as described in the diagram.
So how do they talk to each other? It is actually pretty simple.
Lambda Runtime + Swift Function
Initialization
When a Lambda is launched for the first time, the runtime code is responsible for completing some initialization tasks. Then it processes events invoking the Lambda in a loop until the system decides to terminate the instance. The initialization tasks run once per instantiation of the function to prepare the environment to handle incoming events.
- Retrieve settings — Read environment variables to get details about the function and environment.
HANDLER
– The location to the handler, from the function's configuration. The standard format is `file`.`method`
, where `file`
is the name of the file without an extension, and `method`
is the name of a method or function that's defined in the file. Funnily enough this is pretty much ignored in Swift as the handler function is fixed.
LAMBDA_TASK_ROOT
— The directory that contains the function code.
AWS_LAMBDA_RUNTIME_API
— The host and port of the runtime API. (See defined runtime environment variables for a full list of available variables.)
2. Initialize the function — Load the handler file and run any global or static code that it contains (eg: init functions). Init functions should create static resources like SDK clients and database connections once, and reuse them for multiple incoming events.
3. Handle errors — If an error occurs, call the initialization error API and exit immediately.
Invoking An Event
After completing initialization tasks, the runtime processes incoming events in a loop. Each event is processed using the following steps — in order:
- Get an event — Call the next invocation API to get the next event. The response body contains the event data. Response headers contain the request ID and other information.
- Create a context object — Create an object with context information from environment variables and headers in the API response.
- Invoke the function handler — Pass the event and context object to the handler to run.
- Handle the response — Call the invocation response API to post the response from the handler.
- Handle errors — If an error occurs, call the invocation error API.
- Cleanup — Release unused resources, send data to other services, or perform additional tasks before getting the next event.
Runtime API Calls
Here are the actual lambda runtime API calls that are used to manage the interaction between the Swift code and the Lambda service.
Next Invocation
Path — /runtime/invocation/next
Method — GET
The runtime sends this message to Lambda to request an invocation event. The response body contains the payload from the invocation, which is a JSON document that contains event data from the function trigger. The response headers contain additional data about the invocation.
Invocation Response
Path — /runtime/invocation/`AwsRequestId`/response
Method — POST
After the function has run to completion, the runtime sends an invocation response to Lambda. For synchronous invocations, Lambda sends the response to the client.
Initialization Error
Path — /runtime/init/error
Method — POST
If the function returns an error or the runtime encounters an error during initialization, the runtime uses this method to report the error to Lambda.
Invocation Error
Path — /runtime/invocation/`AwsRequestId`/error
Method — POST
If the function returns an error or the runtime encounters an error, the runtime uses this method to report the error to Lambda.
As you can see it’s not very difficult to understand how the Lambda service and the Runtime API work together. The simple and elegant API provides an interface for managing how Swift code can run on Lambdas . See AWS for more information and documentation details.
As we write more Swift in the Cloud goodies, subscribe and we will send you an email when new content, code and services are released.