File tree Expand file tree Collapse file tree 4 files changed +35
-5
lines changed Expand file tree Collapse file tree 4 files changed +35
-5
lines changed Original file line number Diff line number Diff line change @@ -41,6 +41,17 @@ public enum Lambda {
4141 var logger = logger
4242 do {
4343 while !Task. isCancelled {
44+
45+ if let runtimeClient = runtimeClient as? LambdaRuntimeClient ,
46+ let futureConnectionClosed = await runtimeClient. futureConnectionClosed
47+ {
48+ // Wait for the futureConnectionClosed to complete,
49+ // which will happen when the Lambda HTTP Server (or MockServer) closes the connection
50+ // This allows us to exit the run loop gracefully.
51+ // The futureConnectionClosed is always an error, let it throw to finish the run loop.
52+ let _ = try await futureConnectionClosed. get ( )
53+ }
54+
4455 let ( invocation, writer) = try await runtimeClient. nextInvocation ( )
4556 logger[ metadataKey: " aws-request-id " ] = " \( invocation. metadata. requestID) "
4657
@@ -84,6 +95,7 @@ public enum Lambda {
8495 } catch is CancellationError {
8596 // don't allow cancellation error to propagate further
8697 }
98+
8799 }
88100
89101 /// The default EventLoop the Lambda is scheduled on.
Original file line number Diff line number Diff line change @@ -17,8 +17,14 @@ import ServiceLifecycle
1717
1818extension LambdaRuntime : Service {
1919 public func run( ) async throws {
20- try await cancelWhenGracefulShutdown {
21- try await self . _run ( )
20+ await cancelWhenGracefulShutdown {
21+ do {
22+ try await self . _run ( )
23+ } catch {
24+ // catch top level error that have not been handled before
25+ // this avoids the runtime to crash and generate a backtrace
26+ self . logger. error ( " LambdaRuntime.run() failed with error " , metadata: [ " error " : " \( error) " ] )
27+ }
2228 }
2329 }
2430}
Original file line number Diff line number Diff line change @@ -59,7 +59,13 @@ public final class LambdaRuntime<Handler>: Sendable where Handler: StreamingLamb
5959 #if !ServiceLifecycleSupport
6060 @inlinable
6161 internal func run( ) async throws {
62- try await _run ( )
62+ do {
63+ try await _run ( )
64+ } catch {
65+ // catch top level error that have not been handled before
66+ // this avoids the runtime to crash and generate a backtrace
67+ self . logger. error ( " LambdaRuntime.run() failed with error " , metadata: [ " error " : " \( error) " ] )
68+ }
6369 }
6470 #endif
6571
Original file line number Diff line number Diff line change @@ -92,6 +92,9 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
9292 case closed
9393 }
9494
95+ @usableFromInline
96+ var futureConnectionClosed : EventLoopFuture < LambdaRuntimeError > ? = nil
97+
9598 private let eventLoop : any EventLoop
9699 private let logger : Logger
97100 private let configuration : Configuration
@@ -372,8 +375,10 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
372375 // however, this happens when performance testing against the MockServer
373376 // shutdown this runtime.
374377 // The Lambda service will create a new runtime environment anyway
375- runtimeClient. logger. trace ( " Connection to Lambda API lost, exiting " )
376- exit ( - 1 )
378+ runtimeClient. logger. trace ( " Connection to Lambda API. lost, exiting " )
379+ runtimeClient. futureConnectionClosed = runtimeClient. eventLoop. makeFailedFuture (
380+ LambdaRuntimeError ( code: . connectionToControlPlaneLost)
381+ )
377382 }
378383 }
379384
@@ -392,6 +397,7 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
392397 return handler
393398 }
394399 } catch {
400+
395401 switch self . connectionState {
396402 case . disconnected, . connected:
397403 fatalError ( " Unexpected state: \( self . connectionState) " )
You can’t perform that action at this time.
0 commit comments