-
Notifications
You must be signed in to change notification settings - Fork 123
[HTTPConnectionPool] Implementation switch #427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HTTPConnectionPool] Implementation switch #427
Conversation
1fe5485
to
efaf97c
Compare
func succeed<Delegate: HTTPClientResponseDelegate>(promise: EventLoopPromise<Response>?, | ||
with value: Response, | ||
delegateType: Delegate.Type, | ||
closing: Bool) { | ||
self.releaseAssociatedConnection(delegateType: delegateType, | ||
closing: closing).whenSuccess { | ||
promise?.succeed(value) | ||
} | ||
promise?.succeed(value) | ||
} | ||
|
||
func fail<Delegate: HTTPClientResponseDelegate>(with error: Error, | ||
delegateType: Delegate.Type) { | ||
if let connection = self.connection { | ||
self.releaseAssociatedConnection(delegateType: delegateType, closing: true) | ||
.whenSuccess { | ||
self.promise.fail(error) | ||
connection.channel.close(promise: nil) | ||
} | ||
} else { | ||
// this is used in tests where we don't want to bootstrap the whole connection pool | ||
self.promise.fail(error) | ||
} | ||
} | ||
|
||
func releaseAssociatedConnection<Delegate: HTTPClientResponseDelegate>(delegateType: Delegate.Type, | ||
closing: Bool) -> EventLoopFuture<Void> { | ||
if let connection = self.connection { | ||
// remove read timeout handler | ||
return connection.removeHandler(IdleStateHandler.self).flatMap { | ||
connection.removeHandler(TaskHandler<Delegate>.self) | ||
}.map { | ||
connection.release(closing: closing, logger: self.logger) | ||
}.flatMapError { error in | ||
fatalError("Couldn't remove taskHandler: \(error)") | ||
} | ||
} else { | ||
// TODO: This seems only reached in some internal unit test | ||
// Maybe there could be a better handling in the future to make | ||
// it an error outside of testing contexts | ||
return self.eventLoop.makeSucceededFuture(()) | ||
} | ||
self.promise.fail(error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those functions are not hit from the new implementation. However they are hit from the old implementation. Since we don't want to remove the old implementation in this pr, they should stay for now. We will be able to remove them in a follow up pr.
@@ -290,7 +290,7 @@ class HTTPClientInternalTests: XCTestCase { | |||
let httpBin = HTTPBin() | |||
let httpClient = HTTPClient(eventLoopGroupProvider: .shared(self.clientGroup)) | |||
defer { | |||
XCTAssertNoThrow(try httpClient.syncShutdown(requiresCleanClose: true)) | |||
XCTAssertNoThrow(try httpClient.syncShutdown()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the new implementation we can not make guarantees about the order of succeeding/failing the request (which will lead to a call to syncShutdown
) and marking the connection as idle. For this reason we can not enforce a clean shutdown here.
5601745
to
127abc3
Compare
a45c6a7
to
7cd68cb
Compare
7deafde
to
64eb025
Compare
@@ -34,17 +34,11 @@ extension HTTPClientInternalTests { | |||
("testRequestFinishesAfterRedirectIfServerRespondsBeforeClientFinishes", testRequestFinishesAfterRedirectIfServerRespondsBeforeClientFinishes), | |||
("testProxyStreaming", testProxyStreaming), | |||
("testProxyStreamingFailure", testProxyStreamingFailure), | |||
("testUploadStreamingBackpressure", testUploadStreamingBackpressure), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we have replacements for these tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. This is now tested way lower in the stack on the connection directly.
Use RequestOptions
64eb025
to
a5df5db
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, great work @fabianfett, this looks really good! ✨
Apparently we have a new flaky test (see swift-nightly). Will fix in a follow up PR. Merge this one. |
### Motivation In #427 we switched the implementation over to our new `HTTPConnectionPool`. When we did this, we removed the possibility to access the requests underlying channel. For this reason we needed to remove a number of tests from `HTTPClientInternalTests`. As @weissi pointed out, we should at least still integration test downstream backpressure. This pr replicates the behavior from `HTTPClientInternalTests.testUploadStreamingBackpressure` directly on the `HTTP1Connection`. ### Changes - Move and adjust test from `HTTPClientInternalTests.testUploadStreamingBackpressure` - Rename the test to `testDownloadStreamingBackpressure` since we only test incoming bytes backpressure. ### Result An integration backpressure test, that survived #427.
This is the final pr to switch the implementation over to our new HTTPConnectionPool and Connections. There are some outstanding changes (#425, #426) that we want to land in smaller prs beforehand, but for everyone interested, this is your chance to play with the new implementation.
The failing unit tests are tests related logging, we will need to fix this before we can land this pr.