1313//===----------------------------------------------------------------------===//
1414
1515import Logging
16- import NIOConcurrencyHelpers
1716import NIOCore
1817import Synchronization
1918
@@ -27,10 +26,10 @@ import Foundation
2726// We use an Atomic here to ensure thread safety
2827private let _isRunning = Atomic < Bool > ( false )
2928
30- // we use unchecked here because Handler are not Sendable
31- public final class LambdaRuntime < Handler> : @unchecked Sendable where Handler: StreamingLambdaHandler {
29+ public final class LambdaRuntime < Handler> : Sendable where Handler: StreamingLambdaHandler {
3230 @usableFromInline
33- let handler : Handler
31+ /// we protect the handler behind a Mutex to ensure that we only ever have one copy of it
32+ let handlerMutex : SendingStorage < Handler >
3433 @usableFromInline
3534 let logger : Logger
3635 @usableFromInline
@@ -41,7 +40,7 @@ public final class LambdaRuntime<Handler>: @unchecked Sendable where Handler: St
4140 eventLoop: EventLoop = Lambda . defaultEventLoop,
4241 logger: Logger = Logger ( label: " LambdaRuntime " )
4342 ) {
44- self . handler = handler
43+ self . handlerMutex = SendingStorage ( handler)
4544 self . eventLoop = eventLoop
4645
4746 // by setting the log level here, we understand it can not be changed dynamically at runtime
@@ -80,6 +79,12 @@ public final class LambdaRuntime<Handler>: @unchecked Sendable where Handler: St
8079 _isRunning. store ( false , ordering: . releasing)
8180 }
8281
82+ // The handler can be non-sendable, we want to ensure we only ever have one copy of it
83+ let handler = try ? self . handlerMutex. get ( )
84+ guard let handler else {
85+ throw LambdaRuntimeError ( code: . runtimeCanOnlyBeStartedOnce)
86+ }
87+
8388 // are we running inside an AWS Lambda runtime environment ?
8489 // AWS_LAMBDA_RUNTIME_API is set when running on Lambda
8590 // https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html
@@ -118,7 +123,7 @@ public final class LambdaRuntime<Handler>: @unchecked Sendable where Handler: St
118123 ) { runtimeClient in
119124 try await Lambda . runLoop (
120125 runtimeClient: runtimeClient,
121- handler: self . handler,
126+ handler: handler,
122127 logger: self . logger
123128 )
124129 }
0 commit comments