@@ -80,41 +80,49 @@ public enum Lambda {
80
80
@discardableResult
81
81
internal static func run( configuration: Configuration = . init( ) , factory: @escaping ( EventLoop ) throws -> Handler ) -> Result < Int , Error > {
82
82
self . run ( configuration: configuration, factory: { eventloop -> EventLoopFuture < Handler > in
83
- do {
84
- let handler = try factory ( eventloop)
85
- return eventloop. makeSucceededFuture ( handler)
86
- } catch {
87
- return eventloop. makeFailedFuture ( error)
83
+ let promise = eventloop. makePromise ( of: Handler . self)
84
+ // if we have a callback based handler factory, we offload the creation of the handler
85
+ // onto the default offload queue, to ensure that the eventloop is never blocked.
86
+ Lambda . defaultOffloadQueue. async {
87
+ do {
88
+ promise. succeed ( try factory ( eventloop) )
89
+ } catch {
90
+ promise. fail ( error)
91
+ }
88
92
}
93
+ return promise. futureResult
89
94
} )
90
95
}
91
96
92
97
// for testing and internal use
93
98
@discardableResult
94
99
internal static func run( configuration: Configuration = . init( ) , factory: @escaping HandlerFactory ) -> Result < Int , Error > {
95
- do {
96
- let eventLoopGroup = MultiThreadedEventLoopGroup ( numberOfThreads: 1 ) // only need one thread, will improve performance
97
- defer { try ! eventLoopGroup. syncShutdownGracefully ( ) }
98
- let result = try self . runAsync ( eventLoopGroup: eventLoopGroup, configuration: configuration, factory: factory) . wait ( )
99
- return . success( result)
100
- } catch {
101
- return . failure( error)
102
- }
103
- }
104
-
105
- internal static func runAsync( eventLoopGroup: EventLoopGroup , configuration: Configuration , factory: @escaping HandlerFactory ) -> EventLoopFuture < Int > {
106
100
Backtrace . install ( )
107
101
var logger = Logger ( label: " Lambda " )
108
102
logger. logLevel = configuration. general. logLevel
109
- let lifecycle = Lifecycle ( eventLoop: eventLoopGroup. next ( ) , logger: logger, configuration: configuration, factory: factory)
110
- let signalSource = trap ( signal: configuration. lifecycle. stopSignal) { signal in
111
- logger. info ( " intercepted signal: \( signal) " )
112
- lifecycle. shutdown ( )
113
- }
114
- return lifecycle. start ( ) . flatMap {
115
- return lifecycle. shutdownFuture. always { _ in
103
+
104
+ var result : Result < Int , Error > !
105
+ MultiThreadedEventLoopGroup . withCurrentThreadAsEventLoop { eventLoop in
106
+ let lifecycle = Lifecycle ( eventLoop: eventLoop, logger: logger, configuration: configuration, factory: factory)
107
+ let signalSource = trap ( signal: configuration. lifecycle. stopSignal) { signal in
108
+ logger. info ( " intercepted signal: \( signal) " )
109
+ lifecycle. shutdown ( )
110
+ }
111
+
112
+ lifecycle. start ( ) . flatMap {
113
+ lifecycle. shutdownFuture
114
+ } . whenComplete { lifecycleResult in
116
115
signalSource. cancel ( )
116
+ eventLoop. shutdownGracefully { error in
117
+ if let error = error {
118
+ preconditionFailure ( " Failed to shutdown eventloop: \( error) " )
119
+ }
120
+ }
121
+ result = lifecycleResult
117
122
}
118
123
}
124
+
125
+ logger. info ( " shutdown completed " )
126
+ return result
119
127
}
120
128
}
0 commit comments