From 52689d27e3931fe58d58ce2469e46867503e777b Mon Sep 17 00:00:00 2001 From: Johannes Weiss Date: Tue, 6 Sep 2022 20:28:30 +0100 Subject: [PATCH] add a future-returning shutdown method --- .../AsyncAwait/HTTPClient+shutdown.swift | 2 ++ Sources/AsyncHTTPClient/HTTPClient.swift | 22 +++++++++++++++++++ .../HTTPClientTests+XCTest.swift | 1 + .../HTTPClientTests.swift | 5 +++++ 4 files changed, 30 insertions(+) diff --git a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+shutdown.swift b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+shutdown.swift index 4e7090dbf..36dd3588f 100644 --- a/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+shutdown.swift +++ b/Sources/AsyncHTTPClient/AsyncAwait/HTTPClient+shutdown.swift @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +import NIOCore + #if compiler(>=5.5.2) && canImport(_Concurrency) extension HTTPClient { diff --git a/Sources/AsyncHTTPClient/HTTPClient.swift b/Sources/AsyncHTTPClient/HTTPClient.swift index 55d2573ba..fa9ca0f83 100644 --- a/Sources/AsyncHTTPClient/HTTPClient.swift +++ b/Sources/AsyncHTTPClient/HTTPClient.swift @@ -213,6 +213,28 @@ public class HTTPClient { } #endif + /// Shuts down the ``HTTPClient`` and releases its resources. + /// + /// - note: You cannot use this method if you sharted the ``HTTPClient`` with + /// ``init(eventLoopGroupProvider: .createNew)`` because that will shut down the ``EventLoopGroup`` the + /// returned future would run in. + public func shutdown() -> EventLoopFuture { + switch self.eventLoopGroupProvider { + case .shared(let group): + let promise = group.any().makePromise(of: Void.self) + self.shutdown(queue: .global()) { error in + if let error = error { + promise.fail(error) + } else { + promise.succeed(()) + } + } + return promise.futureResult + case .createNew: + preconditionFailure("Cannot use the shutdown() method which returns a future when owning the EventLoopGroup. Please use the one of the other shutdown methods.") + } + } + private func shutdownEventLoop(queue: DispatchQueue, _ callback: @escaping ShutdownCallback) { self.stateLock.withLock { switch self.eventLoopGroupProvider { diff --git a/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift b/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift index 655e3acc5..2427d6cbf 100644 --- a/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift +++ b/Tests/AsyncHTTPClientTests/HTTPClientTests+XCTest.swift @@ -143,6 +143,7 @@ extension HTTPClientTests { ("testConnectionPoolSizeConfigValueIsRespected", testConnectionPoolSizeConfigValueIsRespected), ("testRequestWithHeaderTransferEncodingIdentityDoesNotFail", testRequestWithHeaderTransferEncodingIdentityDoesNotFail), ("testMassiveDownload", testMassiveDownload), + ("testShutdownWithFutures", testShutdownWithFutures), ] } } diff --git a/Tests/AsyncHTTPClientTests/HTTPClientTests.swift b/Tests/AsyncHTTPClientTests/HTTPClientTests.swift index fd324c68d..3c275c5eb 100644 --- a/Tests/AsyncHTTPClientTests/HTTPClientTests.swift +++ b/Tests/AsyncHTTPClientTests/HTTPClientTests.swift @@ -3463,4 +3463,9 @@ class HTTPClientTests: XCTestCase { XCTAssertEqual(response?.version, .http1_1) XCTAssertEqual(response?.body?.readableBytes, 10_000) } + + func testShutdownWithFutures() { + let httpClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup)) + XCTAssertNoThrow(try httpClient.shutdown().wait()) + } }