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