diff --git a/Sources/AWSLambdaRuntimeCore/Lambda.swift b/Sources/AWSLambdaRuntimeCore/Lambda.swift index a8fa39a7..a4a04cd7 100644 --- a/Sources/AWSLambdaRuntimeCore/Lambda.swift +++ b/Sources/AWSLambdaRuntimeCore/Lambda.swift @@ -76,16 +76,16 @@ public enum Lambda { var result: Result! MultiThreadedEventLoopGroup.withCurrentThreadAsEventLoop { eventLoop in - let lifecycle = Lifecycle(eventLoop: eventLoop, logger: logger, configuration: configuration, factory: factory) + let runtime = LambdaRuntime(eventLoop: eventLoop, logger: logger, configuration: configuration, factory: factory) #if DEBUG let signalSource = trap(signal: configuration.lifecycle.stopSignal) { signal in logger.info("intercepted signal: \(signal)") - lifecycle.shutdown() + runtime.shutdown() } #endif - lifecycle.start().flatMap { - lifecycle.shutdownFuture + runtime.start().flatMap { + runtime.shutdownFuture }.whenComplete { lifecycleResult in #if DEBUG signalSource.cancel() diff --git a/Sources/AWSLambdaRuntimeCore/LambdaLifecycle.swift b/Sources/AWSLambdaRuntimeCore/LambdaLifecycle.swift deleted file mode 100644 index 89bc903b..00000000 --- a/Sources/AWSLambdaRuntimeCore/LambdaLifecycle.swift +++ /dev/null @@ -1,197 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftAWSLambdaRuntime open source project -// -// Copyright (c) 2017-2020 Apple Inc. and the SwiftAWSLambdaRuntime project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Logging -import NIOConcurrencyHelpers -import NIOCore - -extension Lambda { - /// `Lifecycle` manages the Lambda process lifecycle. - /// - /// - note: It is intended to be used within a single `EventLoop`. For this reason this class is not thread safe. - public final class Lifecycle { - private let eventLoop: EventLoop - private let shutdownPromise: EventLoopPromise - private let logger: Logger - private let configuration: Configuration - private let factory: HandlerFactory - - private var state = State.idle { - willSet { - self.eventLoop.assertInEventLoop() - precondition(newValue.order > self.state.order, "invalid state \(newValue) after \(self.state.order)") - } - } - - /// Create a new `Lifecycle`. - /// - /// - parameters: - /// - eventLoop: An `EventLoop` to run the Lambda on. - /// - logger: A `Logger` to log the Lambda events. - /// - factory: A `LambdaHandlerFactory` to create the concrete Lambda handler. - public convenience init(eventLoop: EventLoop, logger: Logger, factory: @escaping HandlerFactory) { - self.init(eventLoop: eventLoop, logger: logger, configuration: .init(), factory: factory) - } - - init(eventLoop: EventLoop, logger: Logger, configuration: Configuration, factory: @escaping HandlerFactory) { - self.eventLoop = eventLoop - self.shutdownPromise = eventLoop.makePromise(of: Int.self) - self.logger = logger - self.configuration = configuration - self.factory = factory - } - - deinit { - guard case .shutdown = self.state else { - preconditionFailure("invalid state \(self.state)") - } - } - - /// The `Lifecycle` shutdown future. - /// - /// - Returns: An `EventLoopFuture` that is fulfilled after the Lambda lifecycle has fully shutdown. - public var shutdownFuture: EventLoopFuture { - self.shutdownPromise.futureResult - } - - /// Start the `Lifecycle`. - /// - /// - Returns: An `EventLoopFuture` that is fulfilled after the Lambda hander has been created and initiliazed, and a first run has been scheduled. - /// - /// - note: This method must be called on the `EventLoop` the `Lifecycle` has been initialized with. - public func start() -> EventLoopFuture { - self.eventLoop.assertInEventLoop() - - logger.info("lambda lifecycle starting with \(self.configuration)") - self.state = .initializing - - var logger = self.logger - logger[metadataKey: "lifecycleId"] = .string(self.configuration.lifecycle.id) - let runner = Runner(eventLoop: self.eventLoop, configuration: self.configuration) - - let startupFuture = runner.initialize(logger: logger, factory: self.factory) - startupFuture.flatMap { handler -> EventLoopFuture<(ByteBufferLambdaHandler, Result)> in - // after the startup future has succeeded, we have a handler that we can use - // to `run` the lambda. - let finishedPromise = self.eventLoop.makePromise(of: Int.self) - self.state = .active(runner, handler) - self.run(promise: finishedPromise) - return finishedPromise.futureResult.mapResult { (handler, $0) } - } - .flatMap { (handler, runnerResult) -> EventLoopFuture in - // after the lambda finishPromise has succeeded or failed we need to - // shutdown the handler - let shutdownContext = ShutdownContext(logger: logger, eventLoop: self.eventLoop) - return handler.shutdown(context: shutdownContext).flatMapErrorThrowing { error in - // if, we had an error shuting down the lambda, we want to concatenate it with - // the runner result - logger.error("Error shutting down handler: \(error)") - throw RuntimeError.shutdownError(shutdownError: error, runnerResult: runnerResult) - }.flatMapResult { (_) -> Result in - // we had no error shutting down the lambda. let's return the runner's result - runnerResult - } - }.always { _ in - // triggered when the Lambda has finished its last run or has a startup failure. - self.markShutdown() - }.cascade(to: self.shutdownPromise) - - return startupFuture.map { _ in } - } - - // MARK: - Private - - #if DEBUG - /// Begin the `Lifecycle` shutdown. Only needed for debugging purposes, hence behind a `DEBUG` flag. - public func shutdown() { - // make this method thread safe by dispatching onto the eventloop - self.eventLoop.execute { - let oldState = self.state - self.state = .shuttingdown - if case .active(let runner, _) = oldState { - runner.cancelWaitingForNextInvocation() - } - } - } - #endif - - private func markShutdown() { - self.state = .shutdown - } - - @inline(__always) - private func run(promise: EventLoopPromise) { - func _run(_ count: Int) { - switch self.state { - case .active(let runner, let handler): - if self.configuration.lifecycle.maxTimes > 0, count >= self.configuration.lifecycle.maxTimes { - return promise.succeed(count) - } - var logger = self.logger - logger[metadataKey: "lifecycleIteration"] = "\(count)" - runner.run(logger: logger, handler: handler).whenComplete { result in - switch result { - case .success: - logger.log(level: .debug, "lambda invocation sequence completed successfully") - // recursive! per aws lambda runtime spec the polling requests are to be done one at a time - _run(count + 1) - case .failure(HTTPClient.Errors.cancelled): - if case .shuttingdown = self.state { - // if we ware shutting down, we expect to that the get next - // invocation request might have been cancelled. For this reason we - // succeed the promise here. - logger.log(level: .info, "lambda invocation sequence has been cancelled for shutdown") - return promise.succeed(count) - } - logger.log(level: .error, "lambda invocation sequence has been cancelled unexpectedly") - promise.fail(HTTPClient.Errors.cancelled) - case .failure(let error): - logger.log(level: .error, "lambda invocation sequence completed with error: \(error)") - promise.fail(error) - } - } - case .shuttingdown: - promise.succeed(count) - default: - preconditionFailure("invalid run state: \(self.state)") - } - } - - _run(0) - } - - private enum State { - case idle - case initializing - case active(Runner, Handler) - case shuttingdown - case shutdown - - internal var order: Int { - switch self { - case .idle: - return 0 - case .initializing: - return 1 - case .active: - return 2 - case .shuttingdown: - return 3 - case .shutdown: - return 4 - } - } - } - } -} diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRuntime.swift b/Sources/AWSLambdaRuntimeCore/LambdaRuntime.swift new file mode 100644 index 00000000..53b9c430 --- /dev/null +++ b/Sources/AWSLambdaRuntimeCore/LambdaRuntime.swift @@ -0,0 +1,195 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftAWSLambdaRuntime open source project +// +// Copyright (c) 2017-2020 Apple Inc. and the SwiftAWSLambdaRuntime project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Logging +import NIOConcurrencyHelpers +import NIOCore + +/// `LambdaRuntime` manages the Lambda process lifecycle. +/// +/// - note: It is intended to be used within a single `EventLoop`. For this reason this class is not thread safe. +public final class LambdaRuntime { + private let eventLoop: EventLoop + private let shutdownPromise: EventLoopPromise + private let logger: Logger + private let configuration: Lambda.Configuration + private let factory: Lambda.HandlerFactory + + private var state = State.idle { + willSet { + self.eventLoop.assertInEventLoop() + precondition(newValue.order > self.state.order, "invalid state \(newValue) after \(self.state.order)") + } + } + + /// Create a new `LambdaRuntime`. + /// + /// - parameters: + /// - eventLoop: An `EventLoop` to run the Lambda on. + /// - logger: A `Logger` to log the Lambda events. + /// - factory: A `LambdaHandlerFactory` to create the concrete Lambda handler. + public convenience init(eventLoop: EventLoop, logger: Logger, factory: @escaping Lambda.HandlerFactory) { + self.init(eventLoop: eventLoop, logger: logger, configuration: .init(), factory: factory) + } + + init(eventLoop: EventLoop, logger: Logger, configuration: Lambda.Configuration, factory: @escaping Lambda.HandlerFactory) { + self.eventLoop = eventLoop + self.shutdownPromise = eventLoop.makePromise(of: Int.self) + self.logger = logger + self.configuration = configuration + self.factory = factory + } + + deinit { + guard case .shutdown = self.state else { + preconditionFailure("invalid state \(self.state)") + } + } + + /// The `Lifecycle` shutdown future. + /// + /// - Returns: An `EventLoopFuture` that is fulfilled after the Lambda lifecycle has fully shutdown. + public var shutdownFuture: EventLoopFuture { + self.shutdownPromise.futureResult + } + + /// Start the `LambdaRuntime`. + /// + /// - Returns: An `EventLoopFuture` that is fulfilled after the Lambda hander has been created and initiliazed, and a first run has been scheduled. + /// + /// - note: This method must be called on the `EventLoop` the `LambdaRuntime` has been initialized with. + public func start() -> EventLoopFuture { + self.eventLoop.assertInEventLoop() + + logger.info("lambda runtime starting with \(self.configuration)") + self.state = .initializing + + var logger = self.logger + logger[metadataKey: "lifecycleId"] = .string(self.configuration.lifecycle.id) + let runner = Lambda.Runner(eventLoop: self.eventLoop, configuration: self.configuration) + + let startupFuture = runner.initialize(logger: logger, factory: self.factory) + startupFuture.flatMap { handler -> EventLoopFuture<(ByteBufferLambdaHandler, Result)> in + // after the startup future has succeeded, we have a handler that we can use + // to `run` the lambda. + let finishedPromise = self.eventLoop.makePromise(of: Int.self) + self.state = .active(runner, handler) + self.run(promise: finishedPromise) + return finishedPromise.futureResult.mapResult { (handler, $0) } + } + .flatMap { (handler, runnerResult) -> EventLoopFuture in + // after the lambda finishPromise has succeeded or failed we need to + // shutdown the handler + let shutdownContext = Lambda.ShutdownContext(logger: logger, eventLoop: self.eventLoop) + return handler.shutdown(context: shutdownContext).flatMapErrorThrowing { error in + // if, we had an error shuting down the lambda, we want to concatenate it with + // the runner result + logger.error("Error shutting down handler: \(error)") + throw Lambda.RuntimeError.shutdownError(shutdownError: error, runnerResult: runnerResult) + }.flatMapResult { (_) -> Result in + // we had no error shutting down the lambda. let's return the runner's result + runnerResult + } + }.always { _ in + // triggered when the Lambda has finished its last run or has a startup failure. + self.markShutdown() + }.cascade(to: self.shutdownPromise) + + return startupFuture.map { _ in } + } + + // MARK: - Private + + #if DEBUG + /// Begin the `LambdaRuntime` shutdown. Only needed for debugging purposes, hence behind a `DEBUG` flag. + public func shutdown() { + // make this method thread safe by dispatching onto the eventloop + self.eventLoop.execute { + let oldState = self.state + self.state = .shuttingdown + if case .active(let runner, _) = oldState { + runner.cancelWaitingForNextInvocation() + } + } + } + #endif + + private func markShutdown() { + self.state = .shutdown + } + + @inline(__always) + private func run(promise: EventLoopPromise) { + func _run(_ count: Int) { + switch self.state { + case .active(let runner, let handler): + if self.configuration.lifecycle.maxTimes > 0, count >= self.configuration.lifecycle.maxTimes { + return promise.succeed(count) + } + var logger = self.logger + logger[metadataKey: "lifecycleIteration"] = "\(count)" + runner.run(logger: logger, handler: handler).whenComplete { result in + switch result { + case .success: + logger.log(level: .debug, "lambda invocation sequence completed successfully") + // recursive! per aws lambda runtime spec the polling requests are to be done one at a time + _run(count + 1) + case .failure(HTTPClient.Errors.cancelled): + if case .shuttingdown = self.state { + // if we ware shutting down, we expect to that the get next + // invocation request might have been cancelled. For this reason we + // succeed the promise here. + logger.log(level: .info, "lambda invocation sequence has been cancelled for shutdown") + return promise.succeed(count) + } + logger.log(level: .error, "lambda invocation sequence has been cancelled unexpectedly") + promise.fail(HTTPClient.Errors.cancelled) + case .failure(let error): + logger.log(level: .error, "lambda invocation sequence completed with error: \(error)") + promise.fail(error) + } + } + case .shuttingdown: + promise.succeed(count) + default: + preconditionFailure("invalid run state: \(self.state)") + } + } + + _run(0) + } + + private enum State { + case idle + case initializing + case active(Lambda.Runner, Lambda.Handler) + case shuttingdown + case shutdown + + internal var order: Int { + switch self { + case .idle: + return 0 + case .initializing: + return 1 + case .active: + return 2 + case .shuttingdown: + return 3 + case .shutdown: + return 4 + } + } + } +} diff --git a/Tests/AWSLambdaRuntimeCoreTests/LambdaHandlerTest.swift b/Tests/AWSLambdaRuntimeCoreTests/LambdaHandlerTest.swift index edf597e4..17e60854 100644 --- a/Tests/AWSLambdaRuntimeCoreTests/LambdaHandlerTest.swift +++ b/Tests/AWSLambdaRuntimeCoreTests/LambdaHandlerTest.swift @@ -47,7 +47,7 @@ class LambdaHandlerTest: XCTestCase { let maxTimes = Int.random(in: 10 ... 20) let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes)) let result = Lambda.run(configuration: configuration, handlerType: TestBootstrapHandler.self) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) @@ -76,7 +76,7 @@ class LambdaHandlerTest: XCTestCase { let maxTimes = Int.random(in: 10 ... 20) let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes)) let result = Lambda.run(configuration: configuration, handlerType: TestBootstrapHandler.self) - assertLambdaLifecycleResult(result, shouldFailWithError: TestError("kaboom")) + assertLambdaRuntimeResult(result, shouldFailWithError: TestError("kaboom")) } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) @@ -99,7 +99,7 @@ class LambdaHandlerTest: XCTestCase { let maxTimes = Int.random(in: 1 ... 10) let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes)) let result = Lambda.run(configuration: configuration, handlerType: Handler.self) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) @@ -121,7 +121,7 @@ class LambdaHandlerTest: XCTestCase { let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes)) let result = Lambda.run(configuration: configuration, handlerType: Handler.self) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) @@ -144,7 +144,7 @@ class LambdaHandlerTest: XCTestCase { let maxTimes = Int.random(in: 1 ... 10) let configuration = Lambda.Configuration(lifecycle: .init(maxTimes: maxTimes)) let result = Lambda.run(configuration: configuration, handlerType: Handler.self) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } #endif @@ -169,7 +169,7 @@ class LambdaHandlerTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { context in context.eventLoop.makeSucceededFuture(Handler()) }) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } func testVoidEventLoopSuccess() { @@ -191,7 +191,7 @@ class LambdaHandlerTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { context in context.eventLoop.makeSucceededFuture(Handler()) }) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } func testEventLoopFailure() { @@ -213,7 +213,7 @@ class LambdaHandlerTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { context in context.eventLoop.makeSucceededFuture(Handler()) }) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } func testEventLoopBootstrapFailure() { @@ -224,7 +224,7 @@ class LambdaHandlerTest: XCTestCase { let result = Lambda.run(configuration: .init(), factory: { context in context.eventLoop.makeFailedFuture(TestError("kaboom")) }) - assertLambdaLifecycleResult(result, shouldFailWithError: TestError("kaboom")) + assertLambdaRuntimeResult(result, shouldFailWithError: TestError("kaboom")) } } diff --git a/Tests/AWSLambdaRuntimeCoreTests/LambdaLifecycleTest.swift b/Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeTest.swift similarity index 86% rename from Tests/AWSLambdaRuntimeCoreTests/LambdaLifecycleTest.swift rename to Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeTest.swift index b0c83113..40b7ca83 100644 --- a/Tests/AWSLambdaRuntimeCoreTests/LambdaLifecycleTest.swift +++ b/Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeTest.swift @@ -19,7 +19,7 @@ import NIOHTTP1 import NIOPosix import XCTest -class LambdaLifecycleTest: XCTestCase { +class LambdaRuntimeTest: XCTestCase { func testShutdownFutureIsFulfilledWithStartUpError() { let server = MockLambdaServer(behavior: FailedBootstrapBehavior()) XCTAssertNoThrow(try server.start().wait()) @@ -30,17 +30,17 @@ class LambdaLifecycleTest: XCTestCase { let eventLoop = eventLoopGroup.next() let logger = Logger(label: "TestLogger") let testError = TestError("kaboom") - let lifecycle = Lambda.Lifecycle(eventLoop: eventLoop, logger: logger, factory: { + let runtime = LambdaRuntime(eventLoop: eventLoop, logger: logger, factory: { $0.eventLoop.makeFailedFuture(testError) }) // eventLoop.submit in this case returns an EventLoopFuture> // which is why we need `wait().wait()` - XCTAssertThrowsError(_ = try eventLoop.flatSubmit { lifecycle.start() }.wait()) { error in + XCTAssertThrowsError(try eventLoop.flatSubmit { runtime.start() }.wait()) { error in XCTAssertEqual(testError, error as? TestError) } - XCTAssertThrowsError(_ = try lifecycle.shutdownFuture.wait()) { error in + XCTAssertThrowsError(_ = try runtime.shutdownFuture.wait()) { error in XCTAssertEqual(testError, error as? TestError) } } @@ -78,12 +78,12 @@ class LambdaLifecycleTest: XCTestCase { let eventLoop = eventLoopGroup.next() let logger = Logger(label: "TestLogger") - let lifecycle = Lambda.Lifecycle(eventLoop: eventLoop, logger: logger, factory: { + let runtime = LambdaRuntime(eventLoop: eventLoop, logger: logger, factory: { $0.eventLoop.makeSucceededFuture(handler) }) - XCTAssertNoThrow(_ = try eventLoop.flatSubmit { lifecycle.start() }.wait()) - XCTAssertThrowsError(_ = try lifecycle.shutdownFuture.wait()) { error in + XCTAssertNoThrow(_ = try eventLoop.flatSubmit { runtime.start() }.wait()) + XCTAssertThrowsError(_ = try runtime.shutdownFuture.wait()) { error in XCTAssertEqual(.badStatusCode(HTTPResponseStatus.internalServerError), error as? Lambda.RuntimeError) } XCTAssertEqual(count, 1) @@ -104,12 +104,12 @@ class LambdaLifecycleTest: XCTestCase { let eventLoop = eventLoopGroup.next() let logger = Logger(label: "TestLogger") - let lifecycle = Lambda.Lifecycle(eventLoop: eventLoop, logger: logger, factory: { + let runtime = LambdaRuntime(eventLoop: eventLoop, logger: logger, factory: { $0.eventLoop.makeSucceededFuture(handler) }) - XCTAssertNoThrow(_ = try eventLoop.flatSubmit { lifecycle.start() }.wait()) - XCTAssertThrowsError(_ = try lifecycle.shutdownFuture.wait()) { error in + XCTAssertNoThrow(_ = try eventLoop.flatSubmit { runtime.start() }.wait()) + XCTAssertThrowsError(_ = try runtime.shutdownFuture.wait()) { error in guard case Lambda.RuntimeError.shutdownError(let shutdownError, .failure(let runtimeError)) = error else { XCTFail("Unexpected error"); return } diff --git a/Tests/AWSLambdaRuntimeCoreTests/LambdaTest.swift b/Tests/AWSLambdaRuntimeCoreTests/LambdaTest.swift index f27600dd..c2819c3e 100644 --- a/Tests/AWSLambdaRuntimeCoreTests/LambdaTest.swift +++ b/Tests/AWSLambdaRuntimeCoreTests/LambdaTest.swift @@ -29,7 +29,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { $0.eventLoop.makeSucceededFuture(EchoHandler()) }) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } func testFailure() { @@ -42,7 +42,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { $0.eventLoop.makeSucceededFuture(FailedHandler("boom")) }) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } func testBootstrapFailure() { @@ -51,7 +51,7 @@ class LambdaTest: XCTestCase { defer { XCTAssertNoThrow(try server.stop().wait()) } let result = Lambda.run(factory: { $0.eventLoop.makeFailedFuture(TestError("kaboom")) }) - assertLambdaLifecycleResult(result, shouldFailWithError: TestError("kaboom")) + assertLambdaRuntimeResult(result, shouldFailWithError: TestError("kaboom")) } func testBootstrapFailureAndReportErrorFailure() { @@ -81,7 +81,7 @@ class LambdaTest: XCTestCase { defer { XCTAssertNoThrow(try server.stop().wait()) } let result = Lambda.run(factory: { $0.eventLoop.makeFailedFuture(TestError("kaboom")) }) - assertLambdaLifecycleResult(result, shouldFailWithError: TestError("kaboom")) + assertLambdaRuntimeResult(result, shouldFailWithError: TestError("kaboom")) } func testStartStopInDebugMode() { @@ -121,7 +121,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { $0.eventLoop.makeSucceededFuture(EchoHandler()) }) - assertLambdaLifecycleResult(result, shouldFailWithError: Lambda.RuntimeError.upstreamError("timeout")) + assertLambdaRuntimeResult(result, shouldFailWithError: Lambda.RuntimeError.upstreamError("timeout")) } func testDisconnect() { @@ -133,7 +133,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { $0.eventLoop.makeSucceededFuture(EchoHandler()) }) - assertLambdaLifecycleResult(result, shouldFailWithError: Lambda.RuntimeError.upstreamError("connectionResetByPeer")) + assertLambdaRuntimeResult(result, shouldFailWithError: Lambda.RuntimeError.upstreamError("connectionResetByPeer")) } func testBigEvent() { @@ -146,7 +146,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { $0.eventLoop.makeSucceededFuture(EchoHandler()) }) - assertLambdaLifecycleResult(result, shoudHaveRun: 1) + assertLambdaRuntimeResult(result, shoudHaveRun: 1) } func testKeepAliveServer() { @@ -159,7 +159,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { $0.eventLoop.makeSucceededFuture(EchoHandler()) }) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } func testNoKeepAliveServer() { @@ -172,7 +172,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: configuration, factory: { $0.eventLoop.makeSucceededFuture(EchoHandler()) }) - assertLambdaLifecycleResult(result, shoudHaveRun: maxTimes) + assertLambdaRuntimeResult(result, shoudHaveRun: maxTimes) } func testServerFailure() { @@ -202,7 +202,7 @@ class LambdaTest: XCTestCase { let result = Lambda.run(configuration: .init(), factory: { $0.eventLoop.makeSucceededFuture(EchoHandler()) }) - assertLambdaLifecycleResult(result, shouldFailWithError: Lambda.RuntimeError.badStatusCode(.internalServerError)) + assertLambdaRuntimeResult(result, shouldFailWithError: Lambda.RuntimeError.badStatusCode(.internalServerError)) } func testDeadline() { diff --git a/Tests/AWSLambdaRuntimeCoreTests/Utils.swift b/Tests/AWSLambdaRuntimeCoreTests/Utils.swift index b6ebf8da..5dd0a5cd 100644 --- a/Tests/AWSLambdaRuntimeCoreTests/Utils.swift +++ b/Tests/AWSLambdaRuntimeCoreTests/Utils.swift @@ -35,7 +35,7 @@ func runLambda(behavior: LambdaServerBehavior, factory: @escaping Lambda.Handler }.wait() } -func assertLambdaLifecycleResult(_ result: Result, shoudHaveRun: Int = 0, shouldFailWithError: Error? = nil, file: StaticString = #file, line: UInt = #line) { +func assertLambdaRuntimeResult(_ result: Result, shoudHaveRun: Int = 0, shouldFailWithError: Error? = nil, file: StaticString = #file, line: UInt = #line) { switch result { case .success where shouldFailWithError != nil: XCTFail("should fail with \(shouldFailWithError!)", file: file, line: line)