Skip to content

Commit 7745274

Browse files
authored
Preserve Types. (#2)
* Preserve Types. * Go inline!
1 parent 91b3a48 commit 7745274

File tree

4 files changed

+60
-50
lines changed

4 files changed

+60
-50
lines changed

Sources/AWSLambdaRuntimeCore/LambdaHandler.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ public protocol SimpleLambdaHandler {
6262
func decode(buffer: ByteBuffer) throws -> Event
6363
}
6464

65+
@usableFromInline
6566
final class CodableSimpleLambdaHandler<Underlying: SimpleLambdaHandler>: ByteBufferLambdaHandler {
66-
private let handler: Underlying
67-
private var outputBuffer: ByteBuffer
67+
@usableFromInline
68+
let handler: Underlying
69+
@usableFromInline
70+
private(set) var outputBuffer: ByteBuffer
6871

6972
@inlinable
7073
static func makeHandler(context: LambdaInitializationContext) -> EventLoopFuture<CodableSimpleLambdaHandler> {
@@ -181,9 +184,12 @@ public protocol LambdaHandler {
181184
func decode(buffer: ByteBuffer) throws -> Event
182185
}
183186

187+
@usableFromInline
184188
final class CodableLambdaHandler<Underlying: LambdaHandler>: ByteBufferLambdaHandler {
185-
private let handler: Underlying
186-
private var outputBuffer: ByteBuffer
189+
@usableFromInline
190+
let handler: Underlying
191+
@usableFromInline
192+
private(set) var outputBuffer: ByteBuffer
187193

188194
@inlinable
189195
static func makeHandler(context: LambdaInitializationContext) -> EventLoopFuture<CodableLambdaHandler> {
@@ -329,9 +335,12 @@ extension EventLoopLambdaHandler where Output == Void {
329335
public func encode(value: Output, into buffer: inout ByteBuffer) throws {}
330336
}
331337

332-
internal final class CodableEventLoopLambdaHandler<Underlying: EventLoopLambdaHandler>: ByteBufferLambdaHandler {
333-
private let handler: Underlying
334-
private var outputBuffer: ByteBuffer
338+
@usableFromInline
339+
final class CodableEventLoopLambdaHandler<Underlying: EventLoopLambdaHandler>: ByteBufferLambdaHandler {
340+
@usableFromInline
341+
let handler: Underlying
342+
@usableFromInline
343+
private(set) var outputBuffer: ByteBuffer
335344

336345
@inlinable
337346
static func makeHandler(context: LambdaInitializationContext) -> EventLoopFuture<CodableEventLoopLambdaHandler> {

Sources/AWSLambdaRuntimeCore/LambdaRunner.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ internal final class LambdaRunner {
3333
/// Run the user provided initializer. This *must* only be called once.
3434
///
3535
/// - Returns: An `EventLoopFuture<LambdaHandler>` fulfilled with the outcome of the initialization.
36-
func initialize(handlerType: (some ByteBufferLambdaHandler).Type, logger: Logger, terminator: LambdaTerminator) -> EventLoopFuture<any ByteBufferLambdaHandler> {
36+
func initialize<Handler: ByteBufferLambdaHandler>(handlerType: Handler.Type, logger: Logger, terminator: LambdaTerminator) -> EventLoopFuture<Handler> {
3737
logger.debug("initializing lambda")
3838
// 1. create the handler from the factory
3939
// 2. report initialization error if one occurred
@@ -45,7 +45,6 @@ internal final class LambdaRunner {
4545
)
4646

4747
return handlerType.makeHandler(context: context)
48-
.map { $0 as any ByteBufferLambdaHandler }
4948
// Hopping back to "our" EventLoop is important in case the factory returns a future
5049
// that originated from a foreign EventLoop/EventLoopGroup.
5150
// This can happen if the factory uses a library (let's say a database client) that manages its own threads/loops
@@ -60,7 +59,7 @@ internal final class LambdaRunner {
6059
}
6160
}
6261

63-
func run(handler: any ByteBufferLambdaHandler, logger: Logger) -> EventLoopFuture<Void> {
62+
func run(handler: some ByteBufferLambdaHandler, logger: Logger) -> EventLoopFuture<Void> {
6463
logger.debug("lambda invocation sequence starting")
6564
// 1. request invocation from lambda runtime engine
6665
self.isGettingNextInvocation = true

Sources/AWSLambdaRuntimeCore/LambdaRuntime.swift

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,67 +19,34 @@ import NIOCore
1919
/// `LambdaRuntime` manages the Lambda process lifecycle.
2020
///
2121
/// Use this API, if you build a higher level web framework which shall be able to run inside the Lambda environment.
22-
public final class LambdaRuntime {
22+
public final class LambdaRuntime<Handler: ByteBufferLambdaHandler> {
2323
private let eventLoop: EventLoop
2424
private let shutdownPromise: EventLoopPromise<Int>
2525
private let logger: Logger
2626
private let configuration: LambdaConfiguration
2727

28-
private let handlerType: any ByteBufferLambdaHandler.Type
29-
3028
private var state = State.idle {
3129
willSet {
3230
self.eventLoop.assertInEventLoop()
3331
precondition(newValue.order > self.state.order, "invalid state \(newValue) after \(self.state.order)")
3432
}
3533
}
3634

37-
/// Create a new `LambdaRuntime`.
38-
///
39-
/// - parameters:
40-
/// - handlerType: The ``SimpleLambdaHandler`` type the `LambdaRuntime` shall create and manage.
41-
/// - eventLoop: An `EventLoop` to run the Lambda on.
42-
/// - logger: A `Logger` to log the Lambda events.
43-
public convenience init<Handler: SimpleLambdaHandler>(_ handlerType: Handler.Type, eventLoop: EventLoop, logger: Logger) {
44-
self.init(CodableSimpleLambdaHandler<Handler>.self, eventLoop: eventLoop, logger: logger)
45-
}
46-
47-
/// Create a new `LambdaRuntime`.
48-
///
49-
/// - parameters:
50-
/// - handlerType: The ``LambdaHandler`` type the `LambdaRuntime` shall create and manage.
51-
/// - eventLoop: An `EventLoop` to run the Lambda on.
52-
/// - logger: A `Logger` to log the Lambda events.
53-
public convenience init<Handler: LambdaHandler>(_ handlerType: Handler.Type, eventLoop: EventLoop, logger: Logger) {
54-
self.init(CodableLambdaHandler<Handler>.self, eventLoop: eventLoop, logger: logger)
55-
}
56-
57-
/// Create a new `LambdaRuntime`.
58-
///
59-
/// - parameters:
60-
/// - handlerType: The ``EventLoopLambdaHandler`` type the `LambdaRuntime` shall create and manage.
61-
/// - eventLoop: An `EventLoop` to run the Lambda on.
62-
/// - logger: A `Logger` to log the Lambda events.
63-
public convenience init<Handler: EventLoopLambdaHandler>(_ handlerType: Handler.Type, eventLoop: EventLoop, logger: Logger) {
64-
self.init(CodableEventLoopLambdaHandler<Handler>.self, eventLoop: eventLoop, logger: logger)
65-
}
66-
6735
/// Create a new `LambdaRuntime`.
6836
///
6937
/// - parameters:
7038
/// - handlerType: The ``ByteBufferLambdaHandler`` type the `LambdaRuntime` shall create and manage.
7139
/// - eventLoop: An `EventLoop` to run the Lambda on.
7240
/// - logger: A `Logger` to log the Lambda events.
73-
public convenience init(_ handlerType: (some ByteBufferLambdaHandler).Type, eventLoop: EventLoop, logger: Logger) {
41+
public convenience init(_ handlerType: Handler.Type, eventLoop: EventLoop, logger: Logger) {
7442
self.init(handlerType: handlerType, eventLoop: eventLoop, logger: logger, configuration: .init())
7543
}
7644

77-
init(handlerType: (some ByteBufferLambdaHandler).Type, eventLoop: EventLoop, logger: Logger, configuration: LambdaConfiguration) {
45+
init(handlerType: Handler.Type, eventLoop: EventLoop, logger: Logger, configuration: LambdaConfiguration) {
7846
self.eventLoop = eventLoop
7947
self.shutdownPromise = eventLoop.makePromise(of: Int.self)
8048
self.logger = logger
8149
self.configuration = configuration
82-
self.handlerType = handlerType
8350
}
8451

8552
deinit {
@@ -118,7 +85,7 @@ public final class LambdaRuntime {
11885
let terminator = LambdaTerminator()
11986
let runner = LambdaRunner(eventLoop: self.eventLoop, configuration: self.configuration)
12087

121-
let startupFuture = runner.initialize(handlerType: self.handlerType, logger: logger, terminator: terminator)
88+
let startupFuture = runner.initialize(handlerType: Handler.self, logger: logger, terminator: terminator)
12289
startupFuture.flatMap { handler -> EventLoopFuture<Result<Int, Error>> in
12390
// after the startup future has succeeded, we have a handler that we can use
12491
// to `run` the lambda.
@@ -229,5 +196,40 @@ public final class LambdaRuntime {
229196
}
230197
}
231198

199+
public enum LambdaRuntimeFactory {
200+
/// Create a new `LambdaRuntime`.
201+
///
202+
/// - parameters:
203+
/// - handlerType: The ``SimpleLambdaHandler`` type the `LambdaRuntime` shall create and manage.
204+
/// - eventLoop: An `EventLoop` to run the Lambda on.
205+
/// - logger: A `Logger` to log the Lambda events.
206+
@inlinable
207+
public static func makeRuntime<H: SimpleLambdaHandler>(_ handlerType: H.Type, eventLoop: any EventLoop, logger: Logger) -> LambdaRuntime<some ByteBufferLambdaHandler> {
208+
LambdaRuntime<CodableSimpleLambdaHandler<H>>(CodableSimpleLambdaHandler<H>.self, eventLoop: eventLoop, logger: logger)
209+
}
210+
211+
/// Create a new `LambdaRuntime`.
212+
///
213+
/// - parameters:
214+
/// - handlerType: The ``LambdaHandler`` type the `LambdaRuntime` shall create and manage.
215+
/// - eventLoop: An `EventLoop` to run the Lambda on.
216+
/// - logger: A `Logger` to log the Lambda events.
217+
@inlinable
218+
public static func makeRuntime<H: LambdaHandler>(_ handlerType: H.Type, eventLoop: any EventLoop, logger: Logger) -> LambdaRuntime<some ByteBufferLambdaHandler> {
219+
LambdaRuntime<CodableLambdaHandler<H>>(CodableLambdaHandler<H>.self, eventLoop: eventLoop, logger: logger)
220+
}
221+
222+
/// Create a new `LambdaRuntime`.
223+
///
224+
/// - parameters:
225+
/// - handlerType: The ``EventLoopLambdaHandler`` type the `LambdaRuntime` shall create and manage.
226+
/// - eventLoop: An `EventLoop` to run the Lambda on.
227+
/// - logger: A `Logger` to log the Lambda events.
228+
@inlinable
229+
public static func makeRuntime<H: EventLoopLambdaHandler>(_ handlerType: H.Type, eventLoop: any EventLoop, logger: Logger) -> LambdaRuntime<some ByteBufferLambdaHandler> {
230+
LambdaRuntime<CodableEventLoopLambdaHandler<H>>(CodableEventLoopLambdaHandler<H>.self, eventLoop: eventLoop, logger: logger)
231+
}
232+
}
233+
232234
/// This is safe since lambda runtime synchronizes by dispatching all methods to a single `EventLoop`
233235
extension LambdaRuntime: @unchecked Sendable {}

Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeTest.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class LambdaRuntimeTest: XCTestCase {
2929

3030
let eventLoop = eventLoopGroup.next()
3131
let logger = Logger(label: "TestLogger")
32-
let runtime = LambdaRuntime(StartupErrorHandler.self, eventLoop: eventLoop, logger: logger)
32+
let runtime = LambdaRuntimeFactory.makeRuntime(StartupErrorHandler.self, eventLoop: eventLoop, logger: logger)
3333

3434
// eventLoop.submit in this case returns an EventLoopFuture<EventLoopFuture<ByteBufferHandler>>
3535
// which is why we need `wait().wait()`
@@ -51,7 +51,7 @@ class LambdaRuntimeTest: XCTestCase {
5151

5252
let eventLoop = eventLoopGroup.next()
5353
let logger = Logger(label: "TestLogger")
54-
let runtime = LambdaRuntime(EchoHandler.self, eventLoop: eventLoop, logger: logger)
54+
let runtime = LambdaRuntimeFactory.makeRuntime(EchoHandler.self, eventLoop: eventLoop, logger: logger)
5555

5656
XCTAssertNoThrow(_ = try eventLoop.flatSubmit { runtime.start() }.wait())
5757
XCTAssertThrowsError(_ = try runtime.shutdownFuture.wait()) {
@@ -98,7 +98,7 @@ class LambdaRuntimeTest: XCTestCase {
9898

9999
let eventLoop = eventLoopGroup.next()
100100
let logger = Logger(label: "TestLogger")
101-
let runtime = LambdaRuntime(ShutdownErrorHandler.self, eventLoop: eventLoop, logger: logger)
101+
let runtime = LambdaRuntimeFactory.makeRuntime(ShutdownErrorHandler.self, eventLoop: eventLoop, logger: logger)
102102

103103
XCTAssertNoThrow(try eventLoop.flatSubmit { runtime.start() }.wait())
104104
XCTAssertThrowsError(try runtime.shutdownFuture.wait()) { error in

0 commit comments

Comments
 (0)