Skip to content

Commit 29244f3

Browse files
committed
cleanup
1 parent 17ed17b commit 29244f3

File tree

13 files changed

+325
-52
lines changed

13 files changed

+325
-52
lines changed

Package.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
// swift-tools-version:5.6
1+
// swift-tools-version:5.7
22

33
import PackageDescription
44

55
let package = Package(
66
name: "swift-aws-lambda-runtime",
7+
platforms: [
8+
.macOS(.v12),
9+
.iOS(.v15),
10+
.tvOS(.v15),
11+
.watchOS(.v8)
12+
],
713
products: [
814
// this library exports `AWSLambdaRuntimeCore` and adds Foundation convenience methods
915
.library(name: "AWSLambdaRuntime", targets: ["AWSLambdaRuntime"]),
@@ -15,7 +21,7 @@ let package = Package(
1521
.library(name: "AWSLambdaTesting", targets: ["AWSLambdaTesting"]),
1622
],
1723
dependencies: [
18-
.package(url: "https://github.com/apple/swift-nio.git", .upToNextMajor(from: "2.33.0")),
24+
.package(url: "https://github.com/apple/swift-nio.git", .upToNextMajor(from: "2.43.1")),
1925
.package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.4.2")),
2026
.package(url: "https://github.com/swift-server/swift-backtrace.git", .upToNextMajor(from: "1.2.3")),
2127
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),

Sources/AWSLambdaRuntime/Lambda+Codable.swift

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,43 @@ import class Foundation.JSONEncoder
1919
import NIOCore
2020
import NIOFoundationCompat
2121

22+
// MARK: - SimpleLambdaHandler Codable support
23+
24+
/// Implementation of `ByteBuffer` to `Event` decoding.
25+
extension SimpleLambdaHandler where Event: Decodable {
26+
@inlinable
27+
public func decode(buffer: ByteBuffer) throws -> Event {
28+
try self.decoder.decode(Event.self, from: buffer)
29+
}
30+
}
31+
32+
/// Implementation of `Output` to `ByteBuffer` encoding.
33+
extension SimpleLambdaHandler where Output: Encodable {
34+
@inlinable
35+
public func encode(value: Output, into buffer: inout ByteBuffer) throws {
36+
try self.encoder.encode(value, into: &buffer)
37+
}
38+
}
39+
40+
/// Default `ByteBuffer` to `Event` decoder using Foundation's `JSONDecoder`.
41+
/// Advanced users who want to inject their own codec can do it by overriding these functions.
42+
extension SimpleLambdaHandler where Event: Decodable {
43+
public var decoder: LambdaCodableDecoder {
44+
Lambda.defaultJSONDecoder
45+
}
46+
}
47+
48+
/// Default `Output` to `ByteBuffer` encoder using Foundation's `JSONEncoder`.
49+
/// Advanced users who want to inject their own codec can do it by overriding these functions.
50+
extension SimpleLambdaHandler where Output: Encodable {
51+
public var encoder: LambdaCodableEncoder {
52+
Lambda.defaultJSONEncoder
53+
}
54+
}
55+
2256
// MARK: - LambdaHandler Codable support
2357

2458
/// Implementation of `ByteBuffer` to `Event` decoding.
25-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
2659
extension LambdaHandler where Event: Decodable {
2760
@inlinable
2861
public func decode(buffer: ByteBuffer) throws -> Event {
@@ -31,7 +64,6 @@ extension LambdaHandler where Event: Decodable {
3164
}
3265

3366
/// Implementation of `Output` to `ByteBuffer` encoding.
34-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
3567
extension LambdaHandler where Output: Encodable {
3668
@inlinable
3769
public func encode(value: Output, into buffer: inout ByteBuffer) throws {
@@ -41,7 +73,6 @@ extension LambdaHandler where Output: Encodable {
4173

4274
/// Default `ByteBuffer` to `Event` decoder using Foundation's `JSONDecoder`.
4375
/// Advanced users who want to inject their own codec can do it by overriding these functions.
44-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
4576
extension LambdaHandler where Event: Decodable {
4677
public var decoder: LambdaCodableDecoder {
4778
Lambda.defaultJSONDecoder
@@ -50,7 +81,6 @@ extension LambdaHandler where Event: Decodable {
5081

5182
/// Default `Output` to `ByteBuffer` encoder using Foundation's `JSONEncoder`.
5283
/// Advanced users who want to inject their own codec can do it by overriding these functions.
53-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
5484
extension LambdaHandler where Output: Encodable {
5585
public var encoder: LambdaCodableEncoder {
5686
Lambda.defaultJSONEncoder

Sources/AWSLambdaRuntimeCore/Lambda+String.swift

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,29 @@
1313
//===----------------------------------------------------------------------===//
1414
import NIOCore
1515

16+
// MARK: - SimpleLambdaHandler String support
17+
18+
extension SimpleLambdaHandler where Event == String {
19+
/// Implementation of a `ByteBuffer` to `String` decoding.
20+
@inlinable
21+
public func decode(buffer: ByteBuffer) throws -> Event {
22+
guard let value = buffer.getString(at: buffer.readerIndex, length: buffer.readableBytes) else {
23+
throw CodecError.invalidString
24+
}
25+
return value
26+
}
27+
}
28+
29+
extension SimpleLambdaHandler where Output == String {
30+
/// Implementation of `String` to `ByteBuffer` encoding.
31+
@inlinable
32+
public func encode(value: Output, into buffer: inout ByteBuffer) throws {
33+
buffer.writeString(value)
34+
}
35+
}
36+
1637
// MARK: - LambdaHandler String support
1738

18-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
1939
extension LambdaHandler where Event == String {
2040
/// Implementation of a `ByteBuffer` to `String` decoding.
2141
@inlinable
@@ -27,7 +47,6 @@ extension LambdaHandler where Event == String {
2747
}
2848
}
2949

30-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
3150
extension LambdaHandler where Output == String {
3251
/// Implementation of `String` to `ByteBuffer` encoding.
3352
@inlinable

Sources/AWSLambdaRuntimeCore/Lambda.swift

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,62 @@ import NIOCore
2424
import NIOPosix
2525

2626
public enum Lambda {
27-
/// Run a Lambda defined by implementing the ``ByteBufferLambdaHandler`` protocol.
28-
/// The Runtime will manage the Lambdas application lifecycle automatically. It will invoke the
29-
/// ``ByteBufferLambdaHandler/makeHandler(context:)`` to create a new Handler.
27+
/// Run a Lambda defined by implementing the ``SimpleLambdaHandler`` protocol.
28+
/// The Runtime will manage the Lambdas application lifecycle automatically.
3029
///
3130
/// - parameters:
3231
/// - configuration: A Lambda runtime configuration object
3332
/// - handlerType: The Handler to create and invoke.
3433
///
3534
/// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine.
35+
internal static func run<Handler: SimpleLambdaHandler>(
36+
configuration: LambdaConfiguration = .init(),
37+
handlerType: Handler.Type
38+
) -> Result<Int, Error> {
39+
Self.run(configuration: configuration, handlerType: CodableSimpleLambdaHandler<Handler>.self)
40+
}
3641

37-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
42+
/// Run a Lambda defined by implementing the ``LambdaHandler`` protocol.
43+
/// The Runtime will manage the Lambdas application lifecycle automatically. It will invoke the
44+
/// ``LambdaHandler/makeHandler(context:)`` to create a new Handler.
45+
///
46+
/// - parameters:
47+
/// - configuration: A Lambda runtime configuration object
48+
/// - handlerType: The Handler to create and invoke.
49+
///
50+
/// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine.
3851
internal static func run<Handler: LambdaHandler>(
3952
configuration: LambdaConfiguration = .init(),
4053
handlerType: Handler.Type
4154
) -> Result<Int, Error> {
4255
Self.run(configuration: configuration, handlerType: CodableLambdaHandler<Handler>.self)
4356
}
4457

58+
/// Run a Lambda defined by implementing the ``EventLoopLambdaHandler`` protocol.
59+
/// The Runtime will manage the Lambdas application lifecycle automatically. It will invoke the
60+
/// ``EventLoopLambdaHandler/makeHandler(context:)`` to create a new Handler.
61+
///
62+
/// - parameters:
63+
/// - configuration: A Lambda runtime configuration object
64+
/// - handlerType: The Handler to create and invoke.
65+
///
66+
/// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine.
4567
internal static func run<Handler: EventLoopLambdaHandler>(
4668
configuration: LambdaConfiguration = .init(),
4769
handlerType: Handler.Type
4870
) -> Result<Int, Error> {
4971
Self.run(configuration: configuration, handlerType: CodableEventLoopLambdaHandler<Handler>.self)
5072
}
5173

74+
/// Run a Lambda defined by implementing the ``ByteBufferLambdaHandler`` protocol.
75+
/// The Runtime will manage the Lambdas application lifecycle automatically. It will invoke the
76+
/// ``ByteBufferLambdaHandler/makeHandler(context:)`` to create a new Handler.
77+
///
78+
/// - parameters:
79+
/// - configuration: A Lambda runtime configuration object
80+
/// - handlerType: The Handler to create and invoke.
81+
///
82+
/// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine.
5283
internal static func run(
5384
configuration: LambdaConfiguration = .init(),
5485
handlerType: (some ByteBufferLambdaHandler).Type
@@ -60,7 +91,7 @@ public enum Lambda {
6091

6192
var result: Result<Int, Error>!
6293
MultiThreadedEventLoopGroup.withCurrentThreadAsEventLoop { eventLoop in
63-
let runtime = LambdaRuntime(handlerType, eventLoop: eventLoop, logger: logger, configuration: configuration)
94+
let runtime = LambdaRuntime(handlerType: handlerType, eventLoop: eventLoop, logger: logger, configuration: configuration)
6495
#if DEBUG
6596
let signalSource = trap(signal: configuration.lifecycle.stopSignal) { signal in
6697
logger.info("intercepted signal: \(signal)")

Sources/AWSLambdaRuntimeCore/LambdaHandler.swift

Lines changed: 101 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,112 @@ import NIOCore
1818
// MARK: - SimpleLambdaHandler
1919

2020
/// Strongly typed, processing protocol for a Lambda that takes a user defined
21-
/// ``LambdaHandler/Event`` and returns a user defined
22-
/// ``LambdaHandler/Output`` asynchronously.
21+
/// ``SimpleLambdaHandler/Event`` and returns a user defined
22+
/// ``SimpleLambdaHandler/Output`` asynchronously.
2323
///
2424
/// - note: Most users should implement the ``LambdaHandler`` protocol instead
2525
/// which defines the Lambda initialization method.
26-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
27-
public protocol SimpleLambdaHandler: LambdaHandler {
26+
public protocol SimpleLambdaHandler {
27+
/// The lambda function's input. In most cases this should be `Codable`. If your event originates from an
28+
/// AWS service, have a look at [AWSLambdaEvents](https://github.com/swift-server/swift-aws-lambda-events),
29+
/// which provides a number of commonly used AWS Event implementations.
30+
associatedtype Event
31+
/// The lambda function's output. Can be `Void`.
32+
associatedtype Output
33+
2834
init()
35+
36+
/// The Lambda handling method.
37+
/// Concrete Lambda handlers implement this method to provide the Lambda functionality.
38+
///
39+
/// - parameters:
40+
/// - event: Event of type `Event` representing the event or request.
41+
/// - context: Runtime ``LambdaContext``.
42+
///
43+
/// - Returns: A Lambda result ot type `Output`.
44+
func handle(_ event: Event, context: LambdaContext) async throws -> Output
45+
46+
/// Encode a response of type ``Output`` to `ByteBuffer`.
47+
/// Concrete Lambda handlers implement this method to provide coding functionality.
48+
/// - parameters:
49+
/// - value: Response of type ``Output``.
50+
/// - buffer: A `ByteBuffer` to encode into, will be overwritten.
51+
///
52+
/// - Returns: A `ByteBuffer` with the encoded version of the `value`.
53+
func encode(value: Output, into buffer: inout ByteBuffer) throws
54+
55+
/// Decode a `ByteBuffer` to a request or event of type ``Event``.
56+
/// Concrete Lambda handlers implement this method to provide coding functionality.
57+
///
58+
/// - parameters:
59+
/// - buffer: The `ByteBuffer` to decode.
60+
///
61+
/// - Returns: A request or event of type ``Event``.
62+
func decode(buffer: ByteBuffer) throws -> Event
63+
}
64+
65+
final class CodableSimpleLambdaHandler<Underlying: SimpleLambdaHandler>: ByteBufferLambdaHandler {
66+
private let handler: Underlying
67+
private var outputBuffer: ByteBuffer
68+
69+
@inlinable
70+
static func makeHandler(context: LambdaInitializationContext) -> EventLoopFuture<CodableSimpleLambdaHandler> {
71+
let promise = context.eventLoop.makePromise(of: CodableSimpleLambdaHandler<Underlying>.self)
72+
promise.completeWithTask {
73+
let handler = Underlying()
74+
return CodableSimpleLambdaHandler(handler: handler, allocator: context.allocator)
75+
}
76+
return promise.futureResult
77+
}
78+
79+
@inlinable
80+
init(handler: Underlying, allocator: ByteBufferAllocator) {
81+
self.handler = handler
82+
self.outputBuffer = allocator.buffer(capacity: 1024 * 1024)
83+
}
84+
85+
@inlinable
86+
func handle(_ buffer: ByteBuffer, context: LambdaContext) -> EventLoopFuture<ByteBuffer?> {
87+
let promise = context.eventLoop.makePromise(of: ByteBuffer?.self)
88+
promise.completeWithTask {
89+
let input: Underlying.Event
90+
do {
91+
input = try self.handler.decode(buffer: buffer)
92+
} catch {
93+
throw CodecError.requestDecoding(error)
94+
}
95+
96+
let output = try await self.handler.handle(input, context: context)
97+
98+
do {
99+
self.outputBuffer.clear()
100+
try self.handler.encode(value: output, into: &self.outputBuffer)
101+
return self.outputBuffer
102+
} catch {
103+
throw CodecError.responseEncoding(error)
104+
}
105+
}
106+
return promise.futureResult
107+
}
108+
}
109+
110+
/// Implementation of `ByteBuffer` to `Void` decoding.
111+
extension SimpleLambdaHandler where Output == Void {
112+
@inlinable
113+
public func encode(value: Output, into buffer: inout ByteBuffer) throws {}
29114
}
30115

31-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
32116
extension SimpleLambdaHandler {
33-
public init(context: LambdaInitializationContext) async throws {
34-
self.init()
117+
/// Initializes and runs the Lambda function.
118+
///
119+
/// If you precede your ``SimpleLambdaHandler`` conformer's declaration with the
120+
/// [@main](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626)
121+
/// attribute, the system calls the conformer's `main()` method to launch the lambda function.
122+
///
123+
/// The lambda runtime provides a default implementation of the method that manages the launch
124+
/// process.
125+
public static func main() {
126+
_ = Lambda.run(configuration: .init(), handlerType: Self.self)
35127
}
36128
}
37129

@@ -44,7 +136,6 @@ extension SimpleLambdaHandler {
44136
/// - note: Most users should implement this protocol instead of the lower
45137
/// level protocols ``EventLoopLambdaHandler`` and
46138
/// ``ByteBufferLambdaHandler``.
47-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
48139
public protocol LambdaHandler {
49140
/// The lambda function's input. In most cases this should be `Codable`. If your event originates from an
50141
/// AWS service, have a look at [AWSLambdaEvents](https://github.com/swift-server/swift-aws-lambda-events),
@@ -90,7 +181,6 @@ public protocol LambdaHandler {
90181
func decode(buffer: ByteBuffer) throws -> Event
91182
}
92183

93-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
94184
final class CodableLambdaHandler<Underlying: LambdaHandler>: ByteBufferLambdaHandler {
95185
private let handler: Underlying
96186
private var outputBuffer: ByteBuffer
@@ -137,17 +227,15 @@ final class CodableLambdaHandler<Underlying: LambdaHandler>: ByteBufferLambdaHan
137227
}
138228

139229
/// Implementation of `ByteBuffer` to `Void` decoding.
140-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
141230
extension LambdaHandler where Output == Void {
142231
@inlinable
143232
public func encode(value: Output, into buffer: inout ByteBuffer) throws {}
144233
}
145234

146-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
147235
extension LambdaHandler {
148236
/// Initializes and runs the Lambda function.
149237
///
150-
/// If you precede your ``ByteBufferLambdaHandler`` conformer's declaration with the
238+
/// If you precede your ``LambdaHandler`` conformer's declaration with the
151239
/// [@main](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626)
152240
/// attribute, the system calls the conformer's `main()` method to launch the lambda function.
153241
///
@@ -161,7 +249,6 @@ extension LambdaHandler {
161249
/// unchecked sendable wrapper for the handler
162250
/// this is safe since lambda runtime is designed to calls the handler serially
163251
@usableFromInline
164-
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
165252
internal struct UncheckedSendableHandler<Underlying: LambdaHandler, Event, Output>: @unchecked Sendable where Event == Underlying.Event, Output == Underlying.Output {
166253
@usableFromInline
167254
let underlying: Underlying
@@ -283,7 +370,7 @@ internal final class CodableEventLoopLambdaHandler<Underlying: EventLoopLambdaHa
283370
extension EventLoopLambdaHandler {
284371
/// Initializes and runs the Lambda function.
285372
///
286-
/// If you precede your ``ByteBufferLambdaHandler`` conformer's declaration with the
373+
/// If you precede your ``EventLoopLambdaHandler`` conformer's declaration with the
287374
/// [@main](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#ID626)
288375
/// attribute, the system calls the conformer's `main()` method to launch the lambda function.
289376
///

Sources/AWSLambdaRuntimeCore/LambdaRunner.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ internal final class LambdaRunner {
6060
}
6161
}
6262

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

0 commit comments

Comments
 (0)