Skip to content

Support for internal Lambda extensions #743

Closed
@ramosbugs

Description

@ramosbugs

First off, thanks for these useful crates! It's nice to see official Rust support from AWS.

The lambda-extension crate currently only supports external Lambda extensions (i.e., those running in a separate binary from the main runtime). AWS Lambda also supports internal Lambda extensions that run in the same process as the runtime, and it would be great if this crate also supported those.

The main requirement for supporting internal extensions is that each internal extension must register itself with the Lambda Runtime API before the runtime thread calls Next:

The Init phase completes after the runtime and each registered extension indicate completion by sending a Next API request.

Once the main runtime calls Next, it's too late to register any additional extensions. The Lambda Runtime API returns an error if an extension tries to register itself at that point.

The current implementation of Extension::run() registers the extension with the Lambda Runtime API and then proceeds to call Next. Since Extension::run() returns a single future that includes both registration and invocation of the extension, there's no way for the caller to determine when registration is complete, and that it's safe to call Runtime::run() (which immediately calls Next and ends the Init phase). In other words, calling Extension::run() and Runtime::run() concurrently creates a race condition between registering the extensions and the runtime calling Next.

A straightforward solution would be to replace (or augment) the Extension::run() function with an API that looks like the following (note the new Extension::register() function and a new type representing a registered extension that's ready to be run):

let extension = Extension::new()
  .with_events(&["INVOKE"])
  .with_events_processor(...);
let registered_extension = extension.register().await;

futures::future::try_join(
  registered_extension.run(),
  Runtime::run(...),
).await

A potential downside to this API is that .with_events will allow a user to attempt to register the SHUTDOWN event, which will fail at runtime since it's not permitted for internal extensions. Also, I'm not sure whether the telemetry and logs processing functionality works for internal extensions or not. These issues could be solved by having separate types for internal and external extensions, along with an enum to represent the supported events instead of accepting raw strings. However, that's a more involved API redesign that may not be worth it at this point.

I'm happy to contribute a PR once there's consensus on the desired API!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions