@@ -17,17 +17,30 @@ import NIO
1717import NIOConcurrencyHelpers
1818
1919extension Lambda {
20- internal final class Lifecycle {
20+ /// `Lifecycle` manages the Lambda process lifecycle.
21+ public final class Lifecycle {
2122 private let eventLoop : EventLoop
23+ private let shutdownPromise : EventLoopPromise < Int >
2224 private let logger : Logger
2325 private let configuration : Configuration
2426 private let factory : LambdaHandlerFactory
2527
2628 private var _state = State . idle
2729 private let stateLock = Lock ( )
2830
31+ /// Create a new `Lifecycle`.
32+ ///
33+ /// - parameters:
34+ /// - eventLoop: An `EventLoop` to run the Lambda on.
35+ /// - logger: A `Logger` to log the Lambda events.
36+ /// - factory: A `LambdaHandlerFactory` to create the concrete Lambda handler.
37+ public convenience init ( eventLoop: EventLoop , logger: Logger , factory: @escaping LambdaHandlerFactory ) {
38+ self . init ( eventLoop: eventLoop, logger: logger, configuration: . init( ) , factory: factory)
39+ }
40+
2941 init ( eventLoop: EventLoop , logger: Logger , configuration: Configuration , factory: @escaping LambdaHandlerFactory ) {
3042 self . eventLoop = eventLoop
43+ self . shutdownPromise = eventLoop. makePromise ( of: Int . self)
3144 self . logger = logger
3245 self . configuration = configuration
3346 self . factory = factory
@@ -39,46 +52,46 @@ extension Lambda {
3952 }
4053 }
4154
42- private var state : State {
43- get {
44- self . stateLock. withLock {
45- self . _state
46- }
47- }
48- set {
49- self . stateLock. withLockVoid {
50- precondition ( newValue. order > _state. order, " invalid state \( newValue) after \( self . _state) " )
51- self . _state = newValue
52- }
53- }
55+ /// The `Lifecycle` shutdown future.
56+ ///
57+ /// - Returns: An `EventLoopFuture` that is fulfilled after the Lambda lifecycle has fully shutdown.
58+ public var shutdownFuture : EventLoopFuture < Int > {
59+ self . shutdownPromise. futureResult
5460 }
5561
56- func start( ) -> EventLoopFuture < Int > {
62+ /// Start the `Lifecycle`.
63+ ///
64+ /// - Returns: An `EventLoopFuture` that is fulfilled after the Lambda hander has been created and initiliazed, and a first run has been schduled.
65+ public func start( ) -> EventLoopFuture < Void > {
5766 logger. info ( " lambda lifecycle starting with \( self . configuration) " )
5867 self . state = . initializing
68+ // triggered when the Lambda has finished its last run
69+ let finishedPromise = self . eventLoop. makePromise ( of: Int . self)
70+ finishedPromise. futureResult. always { _ in
71+ self . markShutdown ( )
72+ } . cascade ( to: self . shutdownPromise)
5973 var logger = self . logger
6074 logger [ metadataKey: " lifecycleId " ] = . string( self . configuration. lifecycle. id)
6175 let runner = Runner ( eventLoop: self . eventLoop, configuration: self . configuration)
62- return runner. initialize ( logger: logger, factory: self . factory) . flatMap { handler in
76+ return runner. initialize ( logger: logger, factory: self . factory) . map { handler in
6377 self . state = . active( runner, handler)
64- return self . run ( )
78+ self . run ( promise : finishedPromise )
6579 }
6680 }
6781
68- func stop( ) {
69- self . logger. debug ( " lambda lifecycle stopping " )
70- self . state = . stopping
82+ // MARK: - Private
83+
84+ /// Begin the `Lifecycle` shutdown.
85+ public func shutdown( ) {
86+ self . state = . shuttingdown
7187 }
7288
73- func shutdown( ) {
74- self . logger. debug ( " lambda lifecycle shutdown " )
89+ private func markShutdown( ) {
7590 self . state = . shutdown
7691 }
7792
7893 @inline ( __always)
79- private func run( ) -> EventLoopFuture < Int > {
80- let promise = self . eventLoop. makePromise ( of: Int . self)
81-
94+ private func run( promise: EventLoopPromise < Int > ) {
8295 func _run( _ count: Int ) {
8396 switch self . state {
8497 case . active( let runner, let handler) :
@@ -96,23 +109,36 @@ extension Lambda {
96109 promise. fail ( error)
97110 }
98111 }
99- case . stopping , . shutdown :
112+ case . shuttingdown :
100113 promise. succeed ( count)
101114 default :
102115 preconditionFailure ( " invalid run state: \( self . state) " )
103116 }
104117 }
105118
106119 _run ( 0 )
120+ }
107121
108- return promise. futureResult
122+ private var state : State {
123+ get {
124+ self . stateLock. withLock {
125+ self . _state
126+ }
127+ }
128+ set {
129+ self . stateLock. withLockVoid {
130+ precondition ( newValue. order > self . _state. order, " invalid state \( newValue) after \( self . _state) " )
131+ self . _state = newValue
132+ }
133+ self . logger. debug ( " lambda lifecycle state: \( newValue) " )
134+ }
109135 }
110136
111137 private enum State {
112138 case idle
113139 case initializing
114140 case active( Runner , ByteBufferLambdaHandler )
115- case stopping
141+ case shuttingdown
116142 case shutdown
117143
118144 internal var order : Int {
@@ -123,7 +149,7 @@ extension Lambda {
123149 return 1
124150 case . active:
125151 return 2
126- case . stopping :
152+ case . shuttingdown :
127153 return 3
128154 case . shutdown:
129155 return 4
0 commit comments