From af3b5f1c97bf2241616be46183544a30d04c8869 Mon Sep 17 00:00:00 2001 From: tom doron Date: Thu, 23 Apr 2020 20:36:16 -0700 Subject: [PATCH 1/4] improve API docs motivation: better documentation, happier users changes: add more inforamtion on public APIs --- Sources/AWSLambdaRuntime/Lambda+Codable.swift | 10 ++++- Sources/AWSLambdaRuntime/Lambda+String.swift | 14 ++++-- Sources/AWSLambdaRuntime/Lambda.swift | 20 +++++++-- Sources/AWSLambdaRuntime/LambdaContext.swift | 15 ++++++- Sources/AWSLambdaRuntime/LambdaHandler.swift | 45 ++++++++++++++++++- .../AWSLambdaRuntime/LambdaLifecycle.swift | 6 +-- Sources/AWSLambdaRuntime/LambdaRunner.swift | 2 +- Tests/AWSLambdaRuntimeTests/Utils.swift | 2 +- 8 files changed, 96 insertions(+), 18 deletions(-) diff --git a/Sources/AWSLambdaRuntime/Lambda+Codable.swift b/Sources/AWSLambdaRuntime/Lambda+Codable.swift index 81445c43..5dd1f2aa 100644 --- a/Sources/AWSLambdaRuntime/Lambda+Codable.swift +++ b/Sources/AWSLambdaRuntime/Lambda+Codable.swift @@ -21,6 +21,9 @@ import NIOFoundationCompat extension Lambda { /// Run a Lambda defined by implementing the `CodableLambdaClosure` function. /// + /// - parameters: + /// - closure: `CodableLambdaClosure` based Lambda. + /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping CodableLambdaClosure) { self.run(closure: closure) @@ -28,6 +31,9 @@ extension Lambda { /// Run a Lambda defined by implementing the `CodableVoidLambdaClosure` function. /// + /// - parameters: + /// - closure: `CodableVoidLambdaClosure` based Lambda. + /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping CodableVoidLambdaClosure) { self.run(closure: closure) @@ -46,10 +52,10 @@ extension Lambda { } } -/// A processing closure for a Lambda that takes a `In` and returns a `Result` via a `CompletionHandler` asynchronously. +/// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. public typealias CodableLambdaClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void -/// A processing closure for a Lambda that takes a `In` and returns a `Result` via a `CompletionHandler` asynchronously. +/// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. public typealias CodableVoidLambdaClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void internal struct CodableLambdaClosureWrapper: LambdaHandler { diff --git a/Sources/AWSLambdaRuntime/Lambda+String.swift b/Sources/AWSLambdaRuntime/Lambda+String.swift index aff8ff19..cabfc76c 100644 --- a/Sources/AWSLambdaRuntime/Lambda+String.swift +++ b/Sources/AWSLambdaRuntime/Lambda+String.swift @@ -17,6 +17,9 @@ import NIO extension Lambda { /// Run a Lambda defined by implementing the `StringLambdaClosure` function. /// + /// - parameters: + /// - closure: `StringLambdaClosure` based Lambda. + /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping StringLambdaClosure) { self.run(closure: closure) @@ -24,6 +27,9 @@ extension Lambda { /// Run a Lambda defined by implementing the `StringVoidLambdaClosure` function. /// + /// - parameters: + /// - closure: `StringVoidLambdaClosure` based Lambda. + /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping StringVoidLambdaClosure) { self.run(closure: closure) @@ -42,10 +48,10 @@ extension Lambda { } } -/// A processing closure for a Lambda that takes a `String` and returns a `Result` via a `CompletionHandler` asynchronously. +/// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. public typealias StringLambdaClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void -/// A processing closure for a Lambda that takes a `String` and returns a `Result` via a `CompletionHandler` asynchronously. +/// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. public typealias StringVoidLambdaClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void internal struct StringLambdaClosureWrapper: LambdaHandler { @@ -78,8 +84,8 @@ internal struct StringVoidLambdaClosureWrapper: LambdaHandler { } } -/// Implementation of a`ByteBuffer` to `String` encoding public extension EventLoopLambdaHandler where In == String { + /// Implementation of a`ByteBuffer` to `String` encoding func decode(buffer: ByteBuffer) throws -> String { var buffer = buffer guard let string = buffer.readString(length: buffer.readableBytes) else { @@ -89,8 +95,8 @@ public extension EventLoopLambdaHandler where In == String { } } -/// Implementation of `String` to `ByteBuffer` decoding public extension EventLoopLambdaHandler where Out == String { + /// Implementation of `String` to `ByteBuffer` decoding func encode(allocator: ByteBufferAllocator, value: String) throws -> ByteBuffer? { // FIXME: reusable buffer var buffer = allocator.buffer(capacity: value.utf8.count) diff --git a/Sources/AWSLambdaRuntime/Lambda.swift b/Sources/AWSLambdaRuntime/Lambda.swift index b46674d6..06299a4f 100644 --- a/Sources/AWSLambdaRuntime/Lambda.swift +++ b/Sources/AWSLambdaRuntime/Lambda.swift @@ -25,6 +25,9 @@ import NIO public enum Lambda { /// Run a Lambda defined by implementing the `LambdaHandler` protocol. /// + /// - parameters: + /// - handler: `ByteBufferLambdaHandler` based Lambda. + /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ handler: ByteBufferLambdaHandler) { self.run(handler: handler) @@ -32,13 +35,19 @@ public enum Lambda { /// Run a Lambda defined by implementing the `LambdaHandler` protocol provided via a `LambdaHandlerFactory`. /// + /// - parameters: + /// - factory: A `ByteBufferLambdaHandler` factory. + /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ factory: @escaping LambdaHandlerFactory) { + public static func run(_ factory: @escaping ByteBufferLambdaHandlerFactory) { self.run(factory: factory) } /// Run a Lambda defined by implementing the `LambdaHandler` protocol provided via a factory, typically a constructor. /// + /// - parameters: + /// - factory: A `ByteBufferLambdaHandler` factory. + /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ factory: @escaping (EventLoop) throws -> ByteBufferLambdaHandler) { self.run(factory: factory) @@ -65,7 +74,7 @@ public enum Lambda { // for testing and internal use @discardableResult - internal static func run(configuration: Configuration = .init(), factory: @escaping LambdaHandlerFactory) -> Result { + internal static func run(configuration: Configuration = .init(), factory: @escaping ByteBufferLambdaHandlerFactory) -> Result { do { let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) // only need one thread, will improve performance defer { try! eventLoopGroup.syncShutdownGracefully() } @@ -76,7 +85,7 @@ public enum Lambda { } } - internal static func runAsync(eventLoopGroup: EventLoopGroup, configuration: Configuration, factory: @escaping LambdaHandlerFactory) -> EventLoopFuture { + internal static func runAsync(eventLoopGroup: EventLoopGroup, configuration: Configuration, factory: @escaping ByteBufferLambdaHandlerFactory) -> EventLoopFuture { Backtrace.install() var logger = Logger(label: "Lambda") logger.logLevel = configuration.general.logLevel @@ -93,4 +102,7 @@ public enum Lambda { } } -public typealias LambdaHandlerFactory = (EventLoop) -> EventLoopFuture +/// `ByteBufferLambdaHandler` factory. +/// +/// A function that takes a `EventLoop` and returns an `EventLoopFuture` of a `ByteBufferLambdaHandler` +public typealias ByteBufferLambdaHandlerFactory = (EventLoop) -> EventLoopFuture diff --git a/Sources/AWSLambdaRuntime/LambdaContext.swift b/Sources/AWSLambdaRuntime/LambdaContext.swift index 85af3e75..52ffefe7 100644 --- a/Sources/AWSLambdaRuntime/LambdaContext.swift +++ b/Sources/AWSLambdaRuntime/LambdaContext.swift @@ -17,6 +17,8 @@ import Logging import NIO extension Lambda { + /// Lambda runtime context. + /// The Lambda runtime generates and passes the `Context` to the Lambda handler as an argument. public final class Context { /// The request ID, which identifies the request that triggered the function invocation. public let requestId: String @@ -36,9 +38,20 @@ extension Lambda { /// For invocations from the AWS Mobile SDK, data about the client application and device. public let clientContext: String? - /// a logger to log + /// `Logger` to log with + /// + /// - note: The `LogLevel` can be configured using the `LOG_LEVEL` environment variable. public let logger: Logger + + /// `EventLoop` to schdule work with . + /// This is useful when implementing `EventLoopLambdaHandler` + /// + /// - note: The `EventLoop` is a shared with the Lambda runtime engine and should be handled with extra care + /// Most importantly the `EventLoop` must never be blocked public let eventLoop: EventLoop + + /// ByteBufferAllocator to allocate `ByteBuffer` + /// This is useful when implementing `EventLoopLambdaHandler` public let allocator: ByteBufferAllocator internal init(requestId: String, diff --git a/Sources/AWSLambdaRuntime/LambdaHandler.swift b/Sources/AWSLambdaRuntime/LambdaHandler.swift index f9bbcdc6..4caab4ac 100644 --- a/Sources/AWSLambdaRuntime/LambdaHandler.swift +++ b/Sources/AWSLambdaRuntime/LambdaHandler.swift @@ -25,8 +25,17 @@ import NIO /// The `EventLoopLambdaHandler` will execute the Lambda on the same `EventLoop` as the core runtime engine, making the processing faster but requires /// more care from the implementation to never block the `EventLoop`. public protocol LambdaHandler: EventLoopLambdaHandler { + /// Defines which `DispatchQueue` the Lambda execution would be offloaded to. var offloadQueue: DispatchQueue { get } + /// The Lambda handling method + /// Concerete Lambda handlers implement this method to provide the Lambda functionality. + /// + /// - parameters: + /// - context: Runtime `Context`. + /// - payload: Payload of type `In` representing the event or request. + /// - callback: Completion handler to report the result of the Lambda back to the runtime engine. + /// The completion handler expecs a `Result` with either a response of type `Out` or an `Error` func handle(context: Lambda.Context, payload: In, callback: @escaping (Result) -> Void) } @@ -66,14 +75,38 @@ public protocol EventLoopLambdaHandler: ByteBufferLambdaHandler { associatedtype In associatedtype Out + /// The Lambda handling method + /// Concerete Lambda handlers implement this method to provide the Lambda functionality. + /// + /// - parameters: + /// - context: Runtime `Context`. + /// - payload: Payload of type `In` representing the event or request. + /// + /// - Returns: An `EventLoopFuture` to report the result of the Lambda back to the runtime engine. + /// The `EventLoopFuture` should be completed with either a response of type `Out` or an `Error` func handle(context: Lambda.Context, payload: In) -> EventLoopFuture + /// Encode a response of type `Out` to `ByteBuffer` + /// Concerete Lambda handlers implement this method to provide coding functionality. + /// - parameters: + /// - allocator: A `ByteBufferAllocator` to help allocate the `ByteBuffer`. + /// - value: Response of type `Out`. + /// + /// - Returns: A `ByteBuffer` with the encoded version of the `value` . func encode(allocator: ByteBufferAllocator, value: Out) throws -> ByteBuffer? + + /// Decode a`ByteBuffer` to a request or event of type `In` + /// Concerete Lambda handlers implement this method to provide coding functionality. + /// + /// - parameters: + /// - buffer: The `ByteBuffer` to decode. + /// + /// - Returns: A request or event of type `In`. func decode(buffer: ByteBuffer) throws -> In } -/// Driver for `ByteBuffer` -> `In` decoding and `Out` -> `ByteBuffer` encoding public extension EventLoopLambdaHandler { + /// Driver for `ByteBuffer` -> `In` decoding and `Out` -> `ByteBuffer` encoding func handle(context: Lambda.Context, payload: ByteBuffer) -> EventLoopFuture { switch self.decodeIn(buffer: payload) { case .failure(let error): @@ -121,7 +154,15 @@ public extension EventLoopLambdaHandler where Out == Void { /// - note: This is a low level protocol designed to power the higher level `EventLoopLambdaHandler` and `LambdaHandler` based APIs. /// Most users are not expected to use this protocol. public protocol ByteBufferLambdaHandler { - /// Handles the Lambda request. + /// The Lambda handling method + /// Concerete Lambda handlers implement this method to provide the Lambda functionality. + /// + /// - parameters: + /// - context: Runtime `Context`. + /// - payload: The event or request payload encoded as `ByteBuffer`. + /// + /// - Returns: An `EventLoopFuture` to report the result of the Lambda back to the runtime engine. + /// The `EventLoopFuture` should be completed with either a response encoded as `ByteBuffer` or an `Error` func handle(context: Lambda.Context, payload: ByteBuffer) -> EventLoopFuture } diff --git a/Sources/AWSLambdaRuntime/LambdaLifecycle.swift b/Sources/AWSLambdaRuntime/LambdaLifecycle.swift index 8ed62d9e..196ae03c 100644 --- a/Sources/AWSLambdaRuntime/LambdaLifecycle.swift +++ b/Sources/AWSLambdaRuntime/LambdaLifecycle.swift @@ -23,7 +23,7 @@ extension Lambda { private let shutdownPromise: EventLoopPromise private let logger: Logger private let configuration: Configuration - private let factory: LambdaHandlerFactory + private let factory: ByteBufferLambdaHandlerFactory private var _state = State.idle private let stateLock = Lock() @@ -34,11 +34,11 @@ extension Lambda { /// - eventLoop: An `EventLoop` to run the Lambda on. /// - logger: A `Logger` to log the Lambda events. /// - factory: A `LambdaHandlerFactory` to create the concrete Lambda handler. - public convenience init(eventLoop: EventLoop, logger: Logger, factory: @escaping LambdaHandlerFactory) { + public convenience init(eventLoop: EventLoop, logger: Logger, factory: @escaping ByteBufferLambdaHandlerFactory) { self.init(eventLoop: eventLoop, logger: logger, configuration: .init(), factory: factory) } - init(eventLoop: EventLoop, logger: Logger, configuration: Configuration, factory: @escaping LambdaHandlerFactory) { + init(eventLoop: EventLoop, logger: Logger, configuration: Configuration, factory: @escaping ByteBufferLambdaHandlerFactory) { self.eventLoop = eventLoop self.shutdownPromise = eventLoop.makePromise(of: Int.self) self.logger = logger diff --git a/Sources/AWSLambdaRuntime/LambdaRunner.swift b/Sources/AWSLambdaRuntime/LambdaRunner.swift index 05891d1d..4d56ef66 100644 --- a/Sources/AWSLambdaRuntime/LambdaRunner.swift +++ b/Sources/AWSLambdaRuntime/LambdaRunner.swift @@ -30,7 +30,7 @@ extension Lambda { /// Run the user provided initializer. This *must* only be called once. /// /// - Returns: An `EventLoopFuture` fulfilled with the outcome of the initialization. - func initialize(logger: Logger, factory: @escaping LambdaHandlerFactory) -> EventLoopFuture { + func initialize(logger: Logger, factory: @escaping ByteBufferLambdaHandlerFactory) -> EventLoopFuture { logger.debug("initializing lambda") // 1. create the handler from the factory // 2. report initialization error if one occured diff --git a/Tests/AWSLambdaRuntimeTests/Utils.swift b/Tests/AWSLambdaRuntimeTests/Utils.swift index c7ff3a09..f8d4e675 100644 --- a/Tests/AWSLambdaRuntimeTests/Utils.swift +++ b/Tests/AWSLambdaRuntimeTests/Utils.swift @@ -21,7 +21,7 @@ func runLambda(behavior: LambdaServerBehavior, handler: ByteBufferLambdaHandler) try runLambda(behavior: behavior, factory: { $0.makeSucceededFuture(handler) }) } -func runLambda(behavior: LambdaServerBehavior, factory: @escaping LambdaHandlerFactory) throws { +func runLambda(behavior: LambdaServerBehavior, factory: @escaping ByteBufferLambdaHandlerFactory) throws { let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } let logger = Logger(label: "TestLogger") From c4816d6fc45969323c8ed815b02e2389ece94e7d Mon Sep 17 00:00:00 2001 From: tomer doron Date: Mon, 27 Apr 2020 10:32:04 -0700 Subject: [PATCH 2/4] Apply suggestions from code review typos Co-Authored-By: Fabian Fett Co-Authored-By: Yim Lee --- Sources/AWSLambdaRuntime/Lambda+String.swift | 4 ++-- Sources/AWSLambdaRuntime/Lambda.swift | 2 ++ Sources/AWSLambdaRuntime/LambdaContext.swift | 10 +++++----- Sources/AWSLambdaRuntime/LambdaHandler.swift | 20 ++++++++++---------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Sources/AWSLambdaRuntime/Lambda+String.swift b/Sources/AWSLambdaRuntime/Lambda+String.swift index cabfc76c..03a670b5 100644 --- a/Sources/AWSLambdaRuntime/Lambda+String.swift +++ b/Sources/AWSLambdaRuntime/Lambda+String.swift @@ -85,7 +85,7 @@ internal struct StringVoidLambdaClosureWrapper: LambdaHandler { } public extension EventLoopLambdaHandler where In == String { - /// Implementation of a`ByteBuffer` to `String` encoding + /// Implementation of a `ByteBuffer` to `String` encoding func decode(buffer: ByteBuffer) throws -> String { var buffer = buffer guard let string = buffer.readString(length: buffer.readableBytes) else { @@ -96,7 +96,7 @@ public extension EventLoopLambdaHandler where In == String { } public extension EventLoopLambdaHandler where Out == String { - /// Implementation of `String` to `ByteBuffer` decoding + /// Implementation of `String` to `ByteBuffer` decoding func encode(allocator: ByteBufferAllocator, value: String) throws -> ByteBuffer? { // FIXME: reusable buffer var buffer = allocator.buffer(capacity: value.utf8.count) diff --git a/Sources/AWSLambdaRuntime/Lambda.swift b/Sources/AWSLambdaRuntime/Lambda.swift index 06299a4f..15e671ba 100644 --- a/Sources/AWSLambdaRuntime/Lambda.swift +++ b/Sources/AWSLambdaRuntime/Lambda.swift @@ -34,6 +34,8 @@ public enum Lambda { } /// Run a Lambda defined by implementing the `LambdaHandler` protocol provided via a `LambdaHandlerFactory`. + /// Use this to initialize all your resources, that you want to cache between invocations. This could be database connections and http clients for example. + /// It is encouraged to use the given EventLoop's conformance to `EventLoopGroup` when initializing NIO dependencies. This will improve overall performance. /// /// - parameters: /// - factory: A `ByteBufferLambdaHandler` factory. diff --git a/Sources/AWSLambdaRuntime/LambdaContext.swift b/Sources/AWSLambdaRuntime/LambdaContext.swift index 52ffefe7..ca69cbf7 100644 --- a/Sources/AWSLambdaRuntime/LambdaContext.swift +++ b/Sources/AWSLambdaRuntime/LambdaContext.swift @@ -43,14 +43,14 @@ extension Lambda { /// - note: The `LogLevel` can be configured using the `LOG_LEVEL` environment variable. public let logger: Logger - /// `EventLoop` to schdule work with . - /// This is useful when implementing `EventLoopLambdaHandler` + /// The `EventLoop` the Lambda is executed on. Use this to schedule work with. + /// This is useful when implementing the `EventLoopLambdaHandler` protocol. /// - /// - note: The `EventLoop` is a shared with the Lambda runtime engine and should be handled with extra care - /// Most importantly the `EventLoop` must never be blocked + /// - note: The `EventLoop` is shared with the Lambda runtime engine and should be handled with extra care. + /// Most importantly the `EventLoop` must never be blocked. public let eventLoop: EventLoop - /// ByteBufferAllocator to allocate `ByteBuffer` + /// `ByteBufferAllocator` to allocate `ByteBuffer` /// This is useful when implementing `EventLoopLambdaHandler` public let allocator: ByteBufferAllocator diff --git a/Sources/AWSLambdaRuntime/LambdaHandler.swift b/Sources/AWSLambdaRuntime/LambdaHandler.swift index 4caab4ac..9294e4f5 100644 --- a/Sources/AWSLambdaRuntime/LambdaHandler.swift +++ b/Sources/AWSLambdaRuntime/LambdaHandler.swift @@ -25,17 +25,17 @@ import NIO /// The `EventLoopLambdaHandler` will execute the Lambda on the same `EventLoop` as the core runtime engine, making the processing faster but requires /// more care from the implementation to never block the `EventLoop`. public protocol LambdaHandler: EventLoopLambdaHandler { - /// Defines which `DispatchQueue` the Lambda execution would be offloaded to. + /// Defines to which `DispatchQueue` the Lambda execution is offloaded to. var offloadQueue: DispatchQueue { get } /// The Lambda handling method - /// Concerete Lambda handlers implement this method to provide the Lambda functionality. + /// Concrete Lambda handlers implement this method to provide the Lambda functionality. /// /// - parameters: /// - context: Runtime `Context`. /// - payload: Payload of type `In` representing the event or request. /// - callback: Completion handler to report the result of the Lambda back to the runtime engine. - /// The completion handler expecs a `Result` with either a response of type `Out` or an `Error` + /// The completion handler expects a `Result` with either a response of type `Out` or an `Error` func handle(context: Lambda.Context, payload: In, callback: @escaping (Result) -> Void) } @@ -76,27 +76,27 @@ public protocol EventLoopLambdaHandler: ByteBufferLambdaHandler { associatedtype Out /// The Lambda handling method - /// Concerete Lambda handlers implement this method to provide the Lambda functionality. + /// Concrete Lambda handlers implement this method to provide the Lambda functionality. /// /// - parameters: /// - context: Runtime `Context`. /// - payload: Payload of type `In` representing the event or request. /// - /// - Returns: An `EventLoopFuture` to report the result of the Lambda back to the runtime engine. + /// - Returns: An `EventLoopFuture` to report the result of the Lambda back to the runtime engine. /// The `EventLoopFuture` should be completed with either a response of type `Out` or an `Error` func handle(context: Lambda.Context, payload: In) -> EventLoopFuture /// Encode a response of type `Out` to `ByteBuffer` - /// Concerete Lambda handlers implement this method to provide coding functionality. + /// Concrete Lambda handlers implement this method to provide coding functionality. /// - parameters: /// - allocator: A `ByteBufferAllocator` to help allocate the `ByteBuffer`. /// - value: Response of type `Out`. /// - /// - Returns: A `ByteBuffer` with the encoded version of the `value` . + /// - Returns: A `ByteBuffer` with the encoded version of the `value`. func encode(allocator: ByteBufferAllocator, value: Out) throws -> ByteBuffer? /// Decode a`ByteBuffer` to a request or event of type `In` - /// Concerete Lambda handlers implement this method to provide coding functionality. + /// Concrete Lambda handlers implement this method to provide coding functionality. /// /// - parameters: /// - buffer: The `ByteBuffer` to decode. @@ -155,13 +155,13 @@ public extension EventLoopLambdaHandler where Out == Void { /// Most users are not expected to use this protocol. public protocol ByteBufferLambdaHandler { /// The Lambda handling method - /// Concerete Lambda handlers implement this method to provide the Lambda functionality. + /// Concrete Lambda handlers implement this method to provide the Lambda functionality. /// /// - parameters: /// - context: Runtime `Context`. /// - payload: The event or request payload encoded as `ByteBuffer`. /// - /// - Returns: An `EventLoopFuture` to report the result of the Lambda back to the runtime engine. + /// - Returns: An `EventLoopFuture` to report the result of the Lambda back to the runtime engine. /// The `EventLoopFuture` should be completed with either a response encoded as `ByteBuffer` or an `Error` func handle(context: Lambda.Context, payload: ByteBuffer) -> EventLoopFuture } From 936a8122823234c11a47f714757f8074966eb121 Mon Sep 17 00:00:00 2001 From: tom doron Date: Tue, 28 Apr 2020 11:19:09 -0700 Subject: [PATCH 3/4] move & simplify type aliases --- Sources/AWSLambdaRuntime/Lambda+Codable.swift | 37 ++++++++++--------- Sources/AWSLambdaRuntime/Lambda+String.swift | 36 +++++++++--------- Sources/AWSLambdaRuntime/Lambda.swift | 28 +++++++------- .../AWSLambdaRuntime/LambdaLifecycle.swift | 8 ++-- Sources/AWSLambdaRuntime/LambdaRunner.swift | 4 +- Sources/AWSLambdaTesting/Lambda+Testing.swift | 16 ++++---- Tests/AWSLambdaRuntimeTests/Utils.swift | 4 +- 7 files changed, 68 insertions(+), 65 deletions(-) diff --git a/Sources/AWSLambdaRuntime/Lambda+Codable.swift b/Sources/AWSLambdaRuntime/Lambda+Codable.swift index e2231d1b..9b8b10f2 100644 --- a/Sources/AWSLambdaRuntime/Lambda+Codable.swift +++ b/Sources/AWSLambdaRuntime/Lambda+Codable.swift @@ -19,52 +19,52 @@ import NIOFoundationCompat /// Extension to the `Lambda` companion to enable execution of Lambdas that take and return `Codable` payloads. extension Lambda { + /// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. + public typealias CodableClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void + /// Run a Lambda defined by implementing the `CodableLambdaClosure` function. /// /// - parameters: /// - closure: `CodableLambdaClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ closure: @escaping CodableLambdaClosure) { + public static func run(_ closure: @escaping CodableClosure) { self.run(closure: closure) } + /// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. + public typealias CodableVoidClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void + /// Run a Lambda defined by implementing the `CodableVoidLambdaClosure` function. /// /// - parameters: /// - closure: `CodableVoidLambdaClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ closure: @escaping CodableVoidLambdaClosure) { + public static func run(_ closure: @escaping CodableVoidClosure) { self.run(closure: closure) } // for testing @discardableResult - internal static func run(configuration: Configuration = .init(), closure: @escaping CodableLambdaClosure) -> Result { - self.run(configuration: configuration, handler: CodableLambdaClosureWrapper(closure)) + internal static func run(configuration: Configuration = .init(), closure: @escaping CodableClosure) -> Result { + self.run(configuration: configuration, handler: CodableClosureWrapper(closure)) } // for testing @discardableResult - internal static func run(configuration: Configuration = .init(), closure: @escaping CodableVoidLambdaClosure) -> Result { - self.run(configuration: configuration, handler: CodableVoidLambdaClosureWrapper(closure)) + internal static func run(configuration: Configuration = .init(), closure: @escaping CodableVoidClosure) -> Result { + self.run(configuration: configuration, handler: CodableVoidClosureWrapper(closure)) } } -/// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. -public typealias CodableLambdaClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void - -/// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. -public typealias CodableVoidLambdaClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void - -internal struct CodableLambdaClosureWrapper: LambdaHandler { +internal struct CodableClosureWrapper: LambdaHandler { typealias In = In typealias Out = Out - private let closure: CodableLambdaClosure + private let closure: Lambda.CodableClosure - init(_ closure: @escaping CodableLambdaClosure) { + init(_ closure: @escaping Lambda.CodableClosure) { self.closure = closure } @@ -73,13 +73,13 @@ internal struct CodableLambdaClosureWrapper: Lamb } } -internal struct CodableVoidLambdaClosureWrapper: LambdaHandler { +internal struct CodableVoidClosureWrapper: LambdaHandler { typealias In = In typealias Out = Void - private let closure: CodableVoidLambdaClosure + private let closure: Lambda.CodableVoidClosure - init(_ closure: @escaping CodableVoidLambdaClosure) { + init(_ closure: @escaping Lambda.CodableVoidClosure) { self.closure = closure } @@ -132,6 +132,7 @@ private extension Lambda { } extension JSONDecoder: LambdaCodableDecoder {} + extension JSONEncoder: LambdaCodableEncoder { public func encode(_ value: T, using allocator: ByteBufferAllocator) throws -> ByteBuffer where T: Encodable { // nio will resize the buffer if necessary diff --git a/Sources/AWSLambdaRuntime/Lambda+String.swift b/Sources/AWSLambdaRuntime/Lambda+String.swift index 03a670b5..62938f17 100644 --- a/Sources/AWSLambdaRuntime/Lambda+String.swift +++ b/Sources/AWSLambdaRuntime/Lambda+String.swift @@ -15,52 +15,52 @@ import NIO /// Extension to the `Lambda` companion to enable execution of Lambdas that take and return `String` payloads. extension Lambda { + /// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. + public typealias StringClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void + /// Run a Lambda defined by implementing the `StringLambdaClosure` function. /// /// - parameters: /// - closure: `StringLambdaClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ closure: @escaping StringLambdaClosure) { + public static func run(_ closure: @escaping StringClosure) { self.run(closure: closure) } + /// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. + public typealias StringVoidClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void + /// Run a Lambda defined by implementing the `StringVoidLambdaClosure` function. /// /// - parameters: /// - closure: `StringVoidLambdaClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ closure: @escaping StringVoidLambdaClosure) { + public static func run(_ closure: @escaping StringVoidClosure) { self.run(closure: closure) } // for testing @discardableResult - internal static func run(configuration: Configuration = .init(), closure: @escaping StringLambdaClosure) -> Result { - self.run(configuration: configuration, handler: StringLambdaClosureWrapper(closure)) + internal static func run(configuration: Configuration = .init(), closure: @escaping StringClosure) -> Result { + self.run(configuration: configuration, handler: StringClosureWrapper(closure)) } // for testing @discardableResult - internal static func run(configuration: Configuration = .init(), closure: @escaping StringVoidLambdaClosure) -> Result { - self.run(configuration: configuration, handler: StringVoidLambdaClosureWrapper(closure)) + internal static func run(configuration: Configuration = .init(), closure: @escaping StringVoidClosure) -> Result { + self.run(configuration: configuration, handler: StringVoidClosureWrapper(closure)) } } -/// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. -public typealias StringLambdaClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void - -/// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. -public typealias StringVoidLambdaClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void - -internal struct StringLambdaClosureWrapper: LambdaHandler { +internal struct StringClosureWrapper: LambdaHandler { typealias In = String typealias Out = String - private let closure: StringLambdaClosure + private let closure: Lambda.StringClosure - init(_ closure: @escaping StringLambdaClosure) { + init(_ closure: @escaping Lambda.StringClosure) { self.closure = closure } @@ -69,13 +69,13 @@ internal struct StringLambdaClosureWrapper: LambdaHandler { } } -internal struct StringVoidLambdaClosureWrapper: LambdaHandler { +internal struct StringVoidClosureWrapper: LambdaHandler { typealias In = String typealias Out = Void - private let closure: StringVoidLambdaClosure + private let closure: Lambda.StringVoidClosure - init(_ closure: @escaping StringVoidLambdaClosure) { + init(_ closure: @escaping Lambda.StringVoidClosure) { self.closure = closure } diff --git a/Sources/AWSLambdaRuntime/Lambda.swift b/Sources/AWSLambdaRuntime/Lambda.swift index 15e671ba..cb952cd6 100644 --- a/Sources/AWSLambdaRuntime/Lambda.swift +++ b/Sources/AWSLambdaRuntime/Lambda.swift @@ -23,13 +23,20 @@ import Logging import NIO public enum Lambda { + public typealias Handler = ByteBufferLambdaHandler + + /// `ByteBufferLambdaHandler` factory. + /// + /// A function that takes a `EventLoop` and returns an `EventLoopFuture` of a `ByteBufferLambdaHandler` + public typealias HandlerFactory = (EventLoop) -> EventLoopFuture + /// Run a Lambda defined by implementing the `LambdaHandler` protocol. /// /// - parameters: /// - handler: `ByteBufferLambdaHandler` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ handler: ByteBufferLambdaHandler) { + public static func run(_ handler: Handler) { self.run(handler: handler) } @@ -41,7 +48,7 @@ public enum Lambda { /// - factory: A `ByteBufferLambdaHandler` factory. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ factory: @escaping ByteBufferLambdaHandlerFactory) { + public static func run(_ factory: @escaping HandlerFactory) { self.run(factory: factory) } @@ -51,20 +58,20 @@ public enum Lambda { /// - factory: A `ByteBufferLambdaHandler` factory. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. - public static func run(_ factory: @escaping (EventLoop) throws -> ByteBufferLambdaHandler) { + public static func run(_ factory: @escaping (EventLoop) throws -> Handler) { self.run(factory: factory) } // for testing and internal use @discardableResult - internal static func run(configuration: Configuration = .init(), handler: ByteBufferLambdaHandler) -> Result { + internal static func run(configuration: Configuration = .init(), handler: Handler) -> Result { self.run(configuration: configuration, factory: { $0.makeSucceededFuture(handler) }) } // for testing and internal use @discardableResult - internal static func run(configuration: Configuration = .init(), factory: @escaping (EventLoop) throws -> ByteBufferLambdaHandler) -> Result { - self.run(configuration: configuration, factory: { eventloop -> EventLoopFuture in + internal static func run(configuration: Configuration = .init(), factory: @escaping (EventLoop) throws -> Handler) -> Result { + self.run(configuration: configuration, factory: { eventloop -> EventLoopFuture in do { let handler = try factory(eventloop) return eventloop.makeSucceededFuture(handler) @@ -76,7 +83,7 @@ public enum Lambda { // for testing and internal use @discardableResult - internal static func run(configuration: Configuration = .init(), factory: @escaping ByteBufferLambdaHandlerFactory) -> Result { + internal static func run(configuration: Configuration = .init(), factory: @escaping HandlerFactory) -> Result { do { let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) // only need one thread, will improve performance defer { try! eventLoopGroup.syncShutdownGracefully() } @@ -87,7 +94,7 @@ public enum Lambda { } } - internal static func runAsync(eventLoopGroup: EventLoopGroup, configuration: Configuration, factory: @escaping ByteBufferLambdaHandlerFactory) -> EventLoopFuture { + internal static func runAsync(eventLoopGroup: EventLoopGroup, configuration: Configuration, factory: @escaping HandlerFactory) -> EventLoopFuture { Backtrace.install() var logger = Logger(label: "Lambda") logger.logLevel = configuration.general.logLevel @@ -103,8 +110,3 @@ public enum Lambda { } } } - -/// `ByteBufferLambdaHandler` factory. -/// -/// A function that takes a `EventLoop` and returns an `EventLoopFuture` of a `ByteBufferLambdaHandler` -public typealias ByteBufferLambdaHandlerFactory = (EventLoop) -> EventLoopFuture diff --git a/Sources/AWSLambdaRuntime/LambdaLifecycle.swift b/Sources/AWSLambdaRuntime/LambdaLifecycle.swift index 196ae03c..03e22cc4 100644 --- a/Sources/AWSLambdaRuntime/LambdaLifecycle.swift +++ b/Sources/AWSLambdaRuntime/LambdaLifecycle.swift @@ -23,7 +23,7 @@ extension Lambda { private let shutdownPromise: EventLoopPromise private let logger: Logger private let configuration: Configuration - private let factory: ByteBufferLambdaHandlerFactory + private let factory: HandlerFactory private var _state = State.idle private let stateLock = Lock() @@ -34,11 +34,11 @@ extension Lambda { /// - eventLoop: An `EventLoop` to run the Lambda on. /// - logger: A `Logger` to log the Lambda events. /// - factory: A `LambdaHandlerFactory` to create the concrete Lambda handler. - public convenience init(eventLoop: EventLoop, logger: Logger, factory: @escaping ByteBufferLambdaHandlerFactory) { + public convenience init(eventLoop: EventLoop, logger: Logger, factory: @escaping HandlerFactory) { self.init(eventLoop: eventLoop, logger: logger, configuration: .init(), factory: factory) } - init(eventLoop: EventLoop, logger: Logger, configuration: Configuration, factory: @escaping ByteBufferLambdaHandlerFactory) { + init(eventLoop: EventLoop, logger: Logger, configuration: Configuration, factory: @escaping HandlerFactory) { self.eventLoop = eventLoop self.shutdownPromise = eventLoop.makePromise(of: Int.self) self.logger = logger @@ -137,7 +137,7 @@ extension Lambda { private enum State { case idle case initializing - case active(Runner, ByteBufferLambdaHandler) + case active(Runner, Handler) case shuttingdown case shutdown diff --git a/Sources/AWSLambdaRuntime/LambdaRunner.swift b/Sources/AWSLambdaRuntime/LambdaRunner.swift index 4d56ef66..10e3bbe4 100644 --- a/Sources/AWSLambdaRuntime/LambdaRunner.swift +++ b/Sources/AWSLambdaRuntime/LambdaRunner.swift @@ -30,7 +30,7 @@ extension Lambda { /// Run the user provided initializer. This *must* only be called once. /// /// - Returns: An `EventLoopFuture` fulfilled with the outcome of the initialization. - func initialize(logger: Logger, factory: @escaping ByteBufferLambdaHandlerFactory) -> EventLoopFuture { + func initialize(logger: Logger, factory: @escaping HandlerFactory) -> EventLoopFuture { logger.debug("initializing lambda") // 1. create the handler from the factory // 2. report initialization error if one occured @@ -43,7 +43,7 @@ extension Lambda { } } - func run(logger: Logger, handler: ByteBufferLambdaHandler) -> EventLoopFuture { + func run(logger: Logger, handler: Handler) -> EventLoopFuture { logger.debug("lambda invocation sequence starting") // 1. request work from lambda runtime engine return self.runtimeClient.requestWork(logger: logger).peekError { error in diff --git a/Sources/AWSLambdaTesting/Lambda+Testing.swift b/Sources/AWSLambdaTesting/Lambda+Testing.swift index 9b828610..d8b2b125 100644 --- a/Sources/AWSLambdaTesting/Lambda+Testing.swift +++ b/Sources/AWSLambdaTesting/Lambda+Testing.swift @@ -39,32 +39,32 @@ extension Lambda { } } - public static func test(_ closure: @escaping StringLambdaClosure, + public static func test(_ closure: @escaping Lambda.StringClosure, with payload: String, using config: TestConfig = .init()) throws -> String { - try Self.test(StringLambdaClosureWrapper(closure), with: payload, using: config) + try Self.test(StringClosureWrapper(closure), with: payload, using: config) } - public static func test(_ closure: @escaping StringVoidLambdaClosure, + public static func test(_ closure: @escaping Lambda.StringVoidClosure, with payload: String, using config: TestConfig = .init()) throws { - _ = try Self.test(StringVoidLambdaClosureWrapper(closure), with: payload, using: config) + _ = try Self.test(StringVoidClosureWrapper(closure), with: payload, using: config) } public static func test( - _ closure: @escaping CodableLambdaClosure, + _ closure: @escaping Lambda.CodableClosure, with payload: In, using config: TestConfig = .init() ) throws -> Out { - try Self.test(CodableLambdaClosureWrapper(closure), with: payload, using: config) + try Self.test(CodableClosureWrapper(closure), with: payload, using: config) } public static func test( - _ closure: @escaping CodableVoidLambdaClosure, + _ closure: @escaping Lambda.CodableVoidClosure, with payload: In, using config: TestConfig = .init() ) throws { - _ = try Self.test(CodableVoidLambdaClosureWrapper(closure), with: payload, using: config) + _ = try Self.test(CodableVoidClosureWrapper(closure), with: payload, using: config) } public static func test( diff --git a/Tests/AWSLambdaRuntimeTests/Utils.swift b/Tests/AWSLambdaRuntimeTests/Utils.swift index f8d4e675..8cf46b6b 100644 --- a/Tests/AWSLambdaRuntimeTests/Utils.swift +++ b/Tests/AWSLambdaRuntimeTests/Utils.swift @@ -17,11 +17,11 @@ import Logging import NIO import XCTest -func runLambda(behavior: LambdaServerBehavior, handler: ByteBufferLambdaHandler) throws { +func runLambda(behavior: LambdaServerBehavior, handler: Lambda.Handler) throws { try runLambda(behavior: behavior, factory: { $0.makeSucceededFuture(handler) }) } -func runLambda(behavior: LambdaServerBehavior, factory: @escaping ByteBufferLambdaHandlerFactory) throws { +func runLambda(behavior: LambdaServerBehavior, factory: @escaping Lambda.HandlerFactory) throws { let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } let logger = Logger(label: "TestLogger") From 3c783c4ddc9779dccd6e4f362e80ccc098fb1b75 Mon Sep 17 00:00:00 2001 From: tomer doron Date: Tue, 28 Apr 2020 11:57:29 -0700 Subject: [PATCH 4/4] Apply suggestions from code review Co-Authored-By: Yim Lee --- Sources/AWSLambdaRuntime/Lambda+Codable.swift | 8 ++++---- Sources/AWSLambdaRuntime/Lambda+String.swift | 12 ++++++------ Sources/AWSLambdaRuntime/Lambda.swift | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Sources/AWSLambdaRuntime/Lambda+Codable.swift b/Sources/AWSLambdaRuntime/Lambda+Codable.swift index 9b8b10f2..e24e736d 100644 --- a/Sources/AWSLambdaRuntime/Lambda+Codable.swift +++ b/Sources/AWSLambdaRuntime/Lambda+Codable.swift @@ -22,10 +22,10 @@ extension Lambda { /// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. public typealias CodableClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void - /// Run a Lambda defined by implementing the `CodableLambdaClosure` function. + /// Run a Lambda defined by implementing the `CodableClosure` function. /// /// - parameters: - /// - closure: `CodableLambdaClosure` based Lambda. + /// - closure: `CodableClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping CodableClosure) { @@ -35,10 +35,10 @@ extension Lambda { /// An asynchronous Lambda Closure that takes a `In: Decodable` and returns a `Result` via a completion handler. public typealias CodableVoidClosure = (Lambda.Context, In, @escaping (Result) -> Void) -> Void - /// Run a Lambda defined by implementing the `CodableVoidLambdaClosure` function. + /// Run a Lambda defined by implementing the `CodableVoidClosure` function. /// /// - parameters: - /// - closure: `CodableVoidLambdaClosure` based Lambda. + /// - closure: `CodableVoidClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping CodableVoidClosure) { diff --git a/Sources/AWSLambdaRuntime/Lambda+String.swift b/Sources/AWSLambdaRuntime/Lambda+String.swift index 62938f17..b9858c50 100644 --- a/Sources/AWSLambdaRuntime/Lambda+String.swift +++ b/Sources/AWSLambdaRuntime/Lambda+String.swift @@ -18,10 +18,10 @@ extension Lambda { /// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. public typealias StringClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void - /// Run a Lambda defined by implementing the `StringLambdaClosure` function. + /// Run a Lambda defined by implementing the `StringClosure` function. /// /// - parameters: - /// - closure: `StringLambdaClosure` based Lambda. + /// - closure: `StringClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping StringClosure) { @@ -31,10 +31,10 @@ extension Lambda { /// An asynchronous Lambda Closure that takes a `String` and returns a `Result` via a completion handler. public typealias StringVoidClosure = (Lambda.Context, String, @escaping (Result) -> Void) -> Void - /// Run a Lambda defined by implementing the `StringVoidLambdaClosure` function. + /// Run a Lambda defined by implementing the `StringVoidClosure` function. /// /// - parameters: - /// - closure: `StringVoidLambdaClosure` based Lambda. + /// - closure: `StringVoidClosure` based Lambda. /// /// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine. public static func run(_ closure: @escaping StringVoidClosure) { @@ -85,7 +85,7 @@ internal struct StringVoidClosureWrapper: LambdaHandler { } public extension EventLoopLambdaHandler where In == String { - /// Implementation of a `ByteBuffer` to `String` encoding + /// Implementation of a `ByteBuffer` to `String` decoding func decode(buffer: ByteBuffer) throws -> String { var buffer = buffer guard let string = buffer.readString(length: buffer.readableBytes) else { @@ -96,7 +96,7 @@ public extension EventLoopLambdaHandler where In == String { } public extension EventLoopLambdaHandler where Out == String { - /// Implementation of `String` to `ByteBuffer` decoding + /// Implementation of `String` to `ByteBuffer` encoding func encode(allocator: ByteBufferAllocator, value: String) throws -> ByteBuffer? { // FIXME: reusable buffer var buffer = allocator.buffer(capacity: value.utf8.count) diff --git a/Sources/AWSLambdaRuntime/Lambda.swift b/Sources/AWSLambdaRuntime/Lambda.swift index cb952cd6..6e9fd9f0 100644 --- a/Sources/AWSLambdaRuntime/Lambda.swift +++ b/Sources/AWSLambdaRuntime/Lambda.swift @@ -41,8 +41,8 @@ public enum Lambda { } /// Run a Lambda defined by implementing the `LambdaHandler` protocol provided via a `LambdaHandlerFactory`. - /// Use this to initialize all your resources, that you want to cache between invocations. This could be database connections and http clients for example. - /// It is encouraged to use the given EventLoop's conformance to `EventLoopGroup` when initializing NIO dependencies. This will improve overall performance. + /// Use this to initialize all your resources that you want to cache between invocations. This could be database connections and HTTP clients for example. + /// It is encouraged to use the given `EventLoop`'s conformance to `EventLoopGroup` when initializing NIO dependencies. This will improve overall performance. /// /// - parameters: /// - factory: A `ByteBufferLambdaHandler` factory.