From 558b74efa550379ce987a30b5d227d63206bb607 Mon Sep 17 00:00:00 2001 From: Fabian Fett <fabianfett@apple.com> Date: Thu, 20 Mar 2025 21:33:09 +0100 Subject: [PATCH 1/3] Add inlinable where potentially usefull --- .../ControlPlaneRequest.swift | 9 ++++++- Sources/AWSLambdaRuntime/Lambda.swift | 1 + Sources/AWSLambdaRuntime/LambdaContext.swift | 2 +- Sources/AWSLambdaRuntime/LambdaRuntime.swift | 2 ++ .../LambdaRuntimeClient.swift | 26 ++++++++++++++++--- .../LambdaRuntimeClientProtocol.swift | 7 ++++- .../AWSLambdaRuntime/LambdaRuntimeError.swift | 7 ++++- Sources/AWSLambdaRuntime/Utils.swift | 1 + 8 files changed, 47 insertions(+), 8 deletions(-) diff --git a/Sources/AWSLambdaRuntime/ControlPlaneRequest.swift b/Sources/AWSLambdaRuntime/ControlPlaneRequest.swift index 29016b0e..233d7aef 100644 --- a/Sources/AWSLambdaRuntime/ControlPlaneRequest.swift +++ b/Sources/AWSLambdaRuntime/ControlPlaneRequest.swift @@ -28,12 +28,19 @@ enum ControlPlaneResponse: Hashable { case error(ErrorResponse) } -package struct InvocationMetadata: Hashable { +@usableFromInline +package struct InvocationMetadata: Hashable, Sendable { + @usableFromInline package let requestID: String + @usableFromInline package let deadlineInMillisSinceEpoch: Int64 + @usableFromInline package let invokedFunctionARN: String + @usableFromInline package let traceID: String + @usableFromInline package let clientContext: String? + @usableFromInline package let cognitoIdentity: String? package init(headers: HTTPHeaders) throws(LambdaRuntimeError) { diff --git a/Sources/AWSLambdaRuntime/Lambda.swift b/Sources/AWSLambdaRuntime/Lambda.swift index 24f10343..e38851c0 100644 --- a/Sources/AWSLambdaRuntime/Lambda.swift +++ b/Sources/AWSLambdaRuntime/Lambda.swift @@ -30,6 +30,7 @@ import ucrt #endif public enum Lambda { + @inlinable package static func runLoop<RuntimeClient: LambdaRuntimeClientProtocol, Handler>( runtimeClient: RuntimeClient, handler: Handler, diff --git a/Sources/AWSLambdaRuntime/LambdaContext.swift b/Sources/AWSLambdaRuntime/LambdaContext.swift index 291a732d..fbf84158 100644 --- a/Sources/AWSLambdaRuntime/LambdaContext.swift +++ b/Sources/AWSLambdaRuntime/LambdaContext.swift @@ -88,7 +88,7 @@ public struct LambdaContext: CustomDebugStringConvertible, Sendable { self.storage.logger } - init( + public init( requestID: String, traceID: String, invokedFunctionARN: String, diff --git a/Sources/AWSLambdaRuntime/LambdaRuntime.swift b/Sources/AWSLambdaRuntime/LambdaRuntime.swift index 6bc2403c..c270b460 100644 --- a/Sources/AWSLambdaRuntime/LambdaRuntime.swift +++ b/Sources/AWSLambdaRuntime/LambdaRuntime.swift @@ -27,6 +27,7 @@ import Foundation // sadly crashes the compiler today. public final class LambdaRuntime<Handler>: @unchecked Sendable where Handler: StreamingLambdaHandler { // TODO: We want to change this to Mutex as soon as this doesn't crash the Swift compiler on Linux anymore + @usableFromInline let handlerMutex: NIOLockedValueBox<Handler?> let logger: Logger let eventLoop: EventLoop @@ -48,6 +49,7 @@ public final class LambdaRuntime<Handler>: @unchecked Sendable where Handler: St self.logger.debug("LambdaRuntime initialized") } + @inlinable public func run() async throws { let handler = self.handlerMutex.withLockedValue { handler in let result = handler diff --git a/Sources/AWSLambdaRuntime/LambdaRuntimeClient.swift b/Sources/AWSLambdaRuntime/LambdaRuntimeClient.swift index 196cbeb1..657127d5 100644 --- a/Sources/AWSLambdaRuntime/LambdaRuntimeClient.swift +++ b/Sources/AWSLambdaRuntime/LambdaRuntimeClient.swift @@ -17,33 +17,47 @@ import NIOCore import NIOHTTP1 import NIOPosix +@usableFromInline final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol { + @usableFromInline nonisolated let unownedExecutor: UnownedSerialExecutor - struct Configuration { + @usableFromInline + struct Configuration: Sendable { var ip: String var port: Int + + @usableFromInline + init(ip: String, port: Int) { + self.ip = ip + self.port = port + } } - struct Writer: LambdaRuntimeClientResponseStreamWriter { + @usableFromInline + struct Writer: LambdaRuntimeClientResponseStreamWriter, Sendable { private var runtimeClient: LambdaRuntimeClient fileprivate init(runtimeClient: LambdaRuntimeClient) { self.runtimeClient = runtimeClient } + @usableFromInline func write(_ buffer: NIOCore.ByteBuffer) async throws { try await self.runtimeClient.write(buffer) } + @usableFromInline func finish() async throws { try await self.runtimeClient.writeAndFinish(nil) } + @usableFromInline func writeAndFinish(_ buffer: NIOCore.ByteBuffer) async throws { try await self.runtimeClient.writeAndFinish(buffer) } + @usableFromInline func reportError(_ error: any Error) async throws { try await self.runtimeClient.reportError(error) } @@ -90,6 +104,7 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol { // being fully closed before we can return from it. private var closingConnections: [any Channel] = [] + @inlinable static func withRuntimeClient<Result>( configuration: Configuration, eventLoop: any EventLoop, @@ -110,14 +125,16 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol { return try result.get() } - private init(configuration: Configuration, eventLoop: any EventLoop, logger: Logger) { + @usableFromInline + init(configuration: Configuration, eventLoop: any EventLoop, logger: Logger) { self.unownedExecutor = eventLoop.executor.asUnownedSerialExecutor() self.configuration = configuration self.eventLoop = eventLoop self.logger = logger } - private func close() async { + @usableFromInline + func close() async { self.logger.trace("Close lambda runtime client") guard case .notClosing = self.closingState else { @@ -144,6 +161,7 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol { } } + @usableFromInline func nextInvocation() async throws -> (Invocation, Writer) { try await withTaskCancellationHandler { switch self.lambdaState { diff --git a/Sources/AWSLambdaRuntime/LambdaRuntimeClientProtocol.swift b/Sources/AWSLambdaRuntime/LambdaRuntimeClientProtocol.swift index 801bdf82..cedd9f35 100644 --- a/Sources/AWSLambdaRuntime/LambdaRuntimeClientProtocol.swift +++ b/Sources/AWSLambdaRuntime/LambdaRuntimeClientProtocol.swift @@ -14,6 +14,7 @@ import NIOCore +@usableFromInline package protocol LambdaRuntimeClientResponseStreamWriter: LambdaResponseStreamWriter { func write(_ buffer: ByteBuffer) async throws func finish() async throws @@ -21,14 +22,18 @@ package protocol LambdaRuntimeClientResponseStreamWriter: LambdaResponseStreamWr func reportError(_ error: any Error) async throws } +@usableFromInline package protocol LambdaRuntimeClientProtocol { associatedtype Writer: LambdaRuntimeClientResponseStreamWriter func nextInvocation() async throws -> (Invocation, Writer) } -package struct Invocation { +@usableFromInline +package struct Invocation: Sendable { + @usableFromInline package var metadata: InvocationMetadata + @usableFromInline package var event: ByteBuffer package init(metadata: InvocationMetadata, event: ByteBuffer) { diff --git a/Sources/AWSLambdaRuntime/LambdaRuntimeError.swift b/Sources/AWSLambdaRuntime/LambdaRuntimeError.swift index a6b4ac66..1a52801e 100644 --- a/Sources/AWSLambdaRuntime/LambdaRuntimeError.swift +++ b/Sources/AWSLambdaRuntime/LambdaRuntimeError.swift @@ -12,8 +12,10 @@ // //===----------------------------------------------------------------------===// +@usableFromInline package struct LambdaRuntimeError: Error { - package enum Code { + @usableFromInline + package enum Code: Sendable { case closingRuntimeClient case connectionToControlPlaneLost @@ -34,12 +36,15 @@ package struct LambdaRuntimeError: Error { case invalidPort } + @usableFromInline package init(code: Code, underlying: (any Error)? = nil) { self.code = code self.underlying = underlying } + @usableFromInline package var code: Code + @usableFromInline package var underlying: (any Error)? } diff --git a/Sources/AWSLambdaRuntime/Utils.swift b/Sources/AWSLambdaRuntime/Utils.swift index 85e6018e..6ed21ed1 100644 --- a/Sources/AWSLambdaRuntime/Utils.swift +++ b/Sources/AWSLambdaRuntime/Utils.swift @@ -59,6 +59,7 @@ enum Signal: Int32 { } extension DispatchWallTime { + @usableFromInline init(millisSinceEpoch: Int64) { let nanoSinceEpoch = UInt64(millisSinceEpoch) * 1_000_000 let seconds = UInt64(nanoSinceEpoch / 1_000_000_000) From a53b7b7468f2f3fd1d49588b067b4ab31d200d15 Mon Sep 17 00:00:00 2001 From: Fabian Fett <fabianfett@apple.com> Date: Thu, 20 Mar 2025 21:40:49 +0100 Subject: [PATCH 2/3] Fix CI --- Sources/AWSLambdaRuntime/LambdaRuntime.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/AWSLambdaRuntime/LambdaRuntime.swift b/Sources/AWSLambdaRuntime/LambdaRuntime.swift index c270b460..5ff0daff 100644 --- a/Sources/AWSLambdaRuntime/LambdaRuntime.swift +++ b/Sources/AWSLambdaRuntime/LambdaRuntime.swift @@ -29,7 +29,9 @@ public final class LambdaRuntime<Handler>: @unchecked Sendable where Handler: St // TODO: We want to change this to Mutex as soon as this doesn't crash the Swift compiler on Linux anymore @usableFromInline let handlerMutex: NIOLockedValueBox<Handler?> + @usableFromInline let logger: Logger + @usableFromInline let eventLoop: EventLoop public init( From d6dd45f5dd36d1f026cb4271fb0b3a4d237e406a Mon Sep 17 00:00:00 2001 From: Fabian Fett <fabianfett@apple.com> Date: Thu, 20 Mar 2025 21:58:35 +0100 Subject: [PATCH 3/3] Fix CI --- Sources/AWSLambdaRuntime/Lambda+LocalServer.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/AWSLambdaRuntime/Lambda+LocalServer.swift b/Sources/AWSLambdaRuntime/Lambda+LocalServer.swift index 4d85f7b2..baa08a44 100644 --- a/Sources/AWSLambdaRuntime/Lambda+LocalServer.swift +++ b/Sources/AWSLambdaRuntime/Lambda+LocalServer.swift @@ -45,6 +45,7 @@ extension Lambda { /// - body: Code to run within the context of the mock server. Typically this would be a Lambda.run function call. /// /// - note: This API is designed strictly for local testing and is behind a DEBUG flag + @usableFromInline static func withLocalServer( invocationEndpoint: String? = nil, _ body: sending @escaping () async throws -> Void