Skip to content

Commit 1cf1045

Browse files
committed
async/await support
1 parent 1bf9c0a commit 1cf1045

File tree

3 files changed

+98
-2
lines changed

3 files changed

+98
-2
lines changed

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ let package = Package(
2424
.byName(name: "AWSLambdaRuntimeCore"),
2525
.product(name: "NIO", package: "swift-nio"),
2626
.product(name: "NIOFoundationCompat", package: "swift-nio"),
27-
]),
27+
], swiftSettings: [.unsafeFlags(["-Xfrontend", "-enable-experimental-concurrency"])]),
2828
.target(name: "AWSLambdaRuntimeCore", dependencies: [
2929
.product(name: "Logging", package: "swift-log"),
3030
.product(name: "Backtrace", package: "swift-backtrace"),
3131
.product(name: "NIOHTTP1", package: "swift-nio"),
32-
]),
32+
], swiftSettings: [.unsafeFlags(["-Xfrontend", "-enable-experimental-concurrency"])]),
3333
.testTarget(name: "AWSLambdaRuntimeCoreTests", dependencies: [
3434
.byName(name: "AWSLambdaRuntimeCore"),
3535
.product(name: "NIOTestUtils", package: "swift-nio"),

Sources/AWSLambdaRuntime/Lambda+Codable.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,69 @@ internal struct CodableVoidClosureWrapper<In: Decodable>: LambdaHandler {
7878
}
7979
}
8080

81+
// MARK: - Async
82+
83+
extension Lambda {
84+
85+
/// An async Lambda Closure that takes a `In: Decodable` and returns an `Out: Encodable`
86+
public typealias CodableAsyncClosure<In: Decodable, Out: Encodable> = (Lambda.Context, In) async throws -> Out
87+
88+
/// Run a Lambda defined by implementing the `CodableAsyncClosure` function.
89+
///
90+
/// - parameters:
91+
/// - closure: `CodableAsyncClosure` based Lambda.
92+
///
93+
/// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine.
94+
public static func run<In: Decodable, Out: Encodable>(_ closure: @escaping CodableAsyncClosure<In, Out>) {
95+
self.run(CodableAsyncWrapper(closure))
96+
}
97+
98+
/// An asynchronous Lambda Closure that takes a `In: Decodable` and returns nothing.
99+
public typealias CodableVoidAsyncClosure<In: Decodable> = (Lambda.Context, In) async throws -> ()
100+
101+
/// Run a Lambda defined by implementing the `CodableVoidAsyncClosure` function.
102+
///
103+
/// - parameters:
104+
/// - closure: `CodableVoidAsyncClosure` based Lambda.
105+
///
106+
/// - note: This is a blocking operation that will run forever, as its lifecycle is managed by the AWS Lambda Runtime Engine.
107+
public static func run<In: Decodable>(_ closure: @escaping CodableVoidAsyncClosure<In>) {
108+
self.run(CodableVoidAsyncWrapper(closure))
109+
}
110+
}
111+
112+
internal struct CodableAsyncWrapper<In: Decodable, Out: Encodable>: AsyncLambdaHandler {
113+
typealias In = In
114+
typealias Out = Out
115+
116+
private let closure: Lambda.CodableAsyncClosure<In, Out>
117+
118+
init(_ closure: @escaping Lambda.CodableAsyncClosure<In, Out>) {
119+
self.closure = closure
120+
}
121+
122+
func handle(context: Lambda.Context, event: In) async throws -> Out {
123+
try await self.closure(context, event)
124+
}
125+
}
126+
127+
internal struct CodableVoidAsyncWrapper<In: Decodable>: AsyncLambdaHandler {
128+
typealias In = In
129+
typealias Out = Void
130+
131+
private let closure: Lambda.CodableVoidAsyncClosure<In>
132+
133+
init(_ closure: @escaping Lambda.CodableVoidAsyncClosure<In>) {
134+
self.closure = closure
135+
}
136+
137+
func handle(context: Lambda.Context, event: In) async throws -> Void {
138+
try await self.closure(context, event)
139+
}
140+
}
141+
142+
// MARK: - Codable support
143+
81144
/// Implementation of a`ByteBuffer` to `In` decoding
82145
extension EventLoopLambdaHandler where In: Decodable {
83146
public func decode(buffer: ByteBuffer) throws -> In {

Sources/AWSLambdaRuntimeCore/LambdaHandler.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,39 @@ extension LambdaHandler {
8383
}
8484
}
8585

86+
// MARK: - AsyncLambdaHandler
87+
88+
/// Strongly typed, processing protocol for a Lambda that takes a user defined `In` and returns a user defined `Out` async.
89+
public protocol AsyncLambdaHandler: EventLoopLambdaHandler {
90+
91+
/// The Lambda handling method
92+
/// Concrete Lambda handlers implement this method to provide the Lambda functionality.
93+
///
94+
/// - parameters:
95+
/// - context: Runtime `Context`.
96+
/// - event: Event of type `In` representing the event or request.
97+
///
98+
/// - Returns: A Lambda result ot type `Out`.
99+
func handle(context: Lambda.Context, event: In) async throws -> Out
100+
}
101+
102+
extension AsyncLambdaHandler {
103+
public func handle(context: Lambda.Context, event: In) -> EventLoopFuture<Out> {
104+
@asyncHandler func _run(context: Lambda.Context, event: In, promise: EventLoopPromise<Out>) {
105+
do {
106+
let result = try await handle(context: context, event: event)
107+
promise.succeed(result)
108+
} catch {
109+
promise.fail(error)
110+
}
111+
}
112+
113+
let promise = context.eventLoop.makePromise(of: Out.self)
114+
_run(context: context, event: event, promise: promise)
115+
return promise.futureResult
116+
}
117+
}
118+
86119
// MARK: - EventLoopLambdaHandler
87120

88121
/// Strongly typed, `EventLoopFuture` based processing protocol for a Lambda that takes a user defined `In` and returns a user defined `Out` asynchronously.

0 commit comments

Comments
 (0)