Skip to content

Commit a772032

Browse files
committed
Review comments addressed.
1 parent 42d6dec commit a772032

File tree

3 files changed

+58
-18
lines changed

3 files changed

+58
-18
lines changed

Sources/AWSLambdaRuntimeCore/LambdaLifecycle.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,19 @@ extension Lambda {
8989
self.run(promise: finishedPromise)
9090
return finishedPromise.futureResult.mapResult { (handler, $0) }
9191
}
92-
.flatMap { (handler, result) -> EventLoopFuture<Int> in
92+
.flatMap { (handler, runnerResult) -> EventLoopFuture<Int> in
93+
// after the lambda finishPromise has succeeded or failed we need to
94+
// shutdown the handler
9395
let shutdownContext = ShutdownContext(logger: logger, eventLoop: self.eventLoop)
94-
return handler.shutdown(context: shutdownContext).recover { error in
96+
return handler.shutdown(context: shutdownContext).flatMapErrorThrowing { error in
97+
// if, we had an error shuting down the lambda, we want to concatenate it with
98+
// the runner result
9599
logger.error("Error shutting down handler: \(error)")
96-
}.flatMapResult { _ in result }
100+
throw RuntimeError.shutdownError(shutdownError: error, runnerResult: runnerResult)
101+
}.flatMapResult { (_) -> Result<Int, Error> in
102+
// we had no error shutting down the lambda. let's return the runner's result
103+
runnerResult
104+
}
97105
}.always { _ in
98106
// triggered when the Lambda has finished its last run or has a startup failure.
99107
self.markShutdown()

Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ internal extension Lambda {
129129
case invocationMissingHeader(String)
130130
case noBody
131131
case json(Error)
132+
case shutdownError(shutdownError: Error, runnerResult: Result<Int, Error>)
132133
}
133134
}
134135

Tests/AWSLambdaRuntimeCoreTests/LambdaLifecycleTest.swift

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,25 @@ class LambdaLifecycleTest: XCTestCase {
4444
}
4545
}
4646

47-
func testSyncShutdownIsCalledWhenLambdaShutsdown() {
48-
struct CallbackLambdaHandler: ByteBufferLambdaHandler {
49-
let handler: (Lambda.Context, ByteBuffer) -> (EventLoopFuture<ByteBuffer?>)
50-
let shutdown: (Lambda.ShutdownContext) -> EventLoopFuture<Void>
51-
52-
init(_ handler: @escaping (Lambda.Context, ByteBuffer) -> (EventLoopFuture<ByteBuffer?>), shutdown: @escaping (Lambda.ShutdownContext) -> EventLoopFuture<Void>) {
53-
self.handler = handler
54-
self.shutdown = shutdown
55-
}
47+
struct CallbackLambdaHandler: ByteBufferLambdaHandler {
48+
let handler: (Lambda.Context, ByteBuffer) -> (EventLoopFuture<ByteBuffer?>)
49+
let shutdown: (Lambda.ShutdownContext) -> EventLoopFuture<Void>
5650

57-
func handle(context: Lambda.Context, event: ByteBuffer) -> EventLoopFuture<ByteBuffer?> {
58-
self.handler(context, event)
59-
}
51+
init(_ handler: @escaping (Lambda.Context, ByteBuffer) -> (EventLoopFuture<ByteBuffer?>), shutdown: @escaping (Lambda.ShutdownContext) -> EventLoopFuture<Void>) {
52+
self.handler = handler
53+
self.shutdown = shutdown
54+
}
6055

61-
func shutdown(context: Lambda.ShutdownContext) -> EventLoopFuture<Void> {
62-
self.shutdown(context)
63-
}
56+
func handle(context: Lambda.Context, event: ByteBuffer) -> EventLoopFuture<ByteBuffer?> {
57+
self.handler(context, event)
6458
}
6559

60+
func shutdown(context: Lambda.ShutdownContext) -> EventLoopFuture<Void> {
61+
self.shutdown(context)
62+
}
63+
}
64+
65+
func testShutdownIsCalledWhenLambdaShutsdown() {
6666
let server = MockLambdaServer(behavior: BadBehavior())
6767
XCTAssertNoThrow(try server.start().wait())
6868
defer { XCTAssertNoThrow(try server.stop().wait()) }
@@ -87,6 +87,37 @@ class LambdaLifecycleTest: XCTestCase {
8787
}
8888
XCTAssertEqual(count, 1)
8989
}
90+
91+
func testLambdaResultIfShutsdownIsUnclean() {
92+
let server = MockLambdaServer(behavior: BadBehavior())
93+
XCTAssertNoThrow(try server.start().wait())
94+
defer { XCTAssertNoThrow(try server.stop().wait()) }
95+
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
96+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
97+
98+
var count = 0
99+
let handler = CallbackLambdaHandler({ XCTFail("Should not be reached"); return $0.eventLoop.makeSucceededFuture($1) }) { context in
100+
count += 1
101+
return context.eventLoop.makeFailedFuture(TestError("kaboom"))
102+
}
103+
104+
let eventLoop = eventLoopGroup.next()
105+
let logger = Logger(label: "TestLogger")
106+
let lifecycle = Lambda.Lifecycle(eventLoop: eventLoop, logger: logger, factory: {
107+
$0.makeSucceededFuture(handler)
108+
})
109+
110+
XCTAssertNoThrow(_ = try eventLoop.flatSubmit { lifecycle.start() }.wait())
111+
XCTAssertThrowsError(_ = try lifecycle.shutdownFuture.wait()) { error in
112+
guard case Lambda.RuntimeError.shutdownError(let shutdownError, .failure(let runtimeError)) = error else {
113+
XCTFail("Unexpected error"); return
114+
}
115+
116+
XCTAssertEqual(shutdownError as? TestError, TestError("kaboom"))
117+
XCTAssertEqual(runtimeError as? Lambda.RuntimeError, .badStatusCode(.internalServerError))
118+
}
119+
XCTAssertEqual(count, 1)
120+
}
90121
}
91122

92123
struct BadBehavior: LambdaServerBehavior {

0 commit comments

Comments
 (0)