Skip to content

[HTTP2] integrate HTTP2StateMachine into HTTPConnectionPool.StateMachine #462

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

Merged

Conversation

dnadoba
Copy link
Collaborator

@dnadoba dnadoba commented Oct 28, 2021

Motivation

To support HTTP/2 we need to integrate the HTTP2StateMachine into the new connection pool.

Changes

  • introduce a new http2 state case in HTTPConnectionPool.StateMachine
  • forwards HTTP/1 and HTTP/2 state machine calls to the HTTP2 machine if we are currently in http2 state.
  • Fixed a bug in http2 backoff connection creation (created to many connections)
  • Fixed a bug in http2 to http1 migration (returned boolean in removeAll(_:) was the inverse of what we actually wanted) which resulted in duplicated connections and lost connections.
    Note that we should never hit the HTTP2StateMachine or be in the http2 state because HTTP/2 is still disabled.
  • add tests for bug fixes
  • add integration tests for HTTPConnectionPool.StateMachine

@dnadoba dnadoba force-pushed the dn-http2-state-machine-integration branch from 866f570 to 32c4e7f Compare October 28, 2021 20:02
Comment on lines 196 to 199
http1.failedToCreateNewConnection(
error,
connectionID: connectionID
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: maybe make this one line.

And I know you just kept my style ;)

)

let newConnectionAction = http1StateMachine.migrateFromHTTP2(
http2State: http2StateMachine,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What properties are needed from the h2 state machine. Could those be passed explicitly? I should have catched this earlier. We create a dependency cycle on the state machines here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http1Connections, connections and requests. The method which takes a HTTP2StateMachine:

mutating func migrateFromHTTP1(
http1State: HTTP1StateMachine,
newHTTP2Connection: Connection,
maxConcurrentStreams: Int
) -> Action {

is just a convenience overload for:
mutating func migrateFromHTTP1(
http1Connections: HTTP1Connections,
http2Connections: HTTP2Connections? = nil,
requests: RequestQueue,
newHTTP2Connection: Connection,
maxConcurrentStreams: Int
) -> Action {

which takes everything as separate arguments. We can just remove the convenience overload if you want.

idGenerator: self.idGenerator
)
let migrationAction = http2StateMachine.migrateFromHTTP1(
http1State: http1StateMachine,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above. Could we pass the needed properties explicitly?

- fix code formatting style
- remove migration convience overload
Copy link
Member

@fabianfett fabianfett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Very excited about this!

@fabianfett fabianfett requested a review from Lukasa October 29, 2021 11:04
Copy link
Collaborator

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR as-is is good. I've left two notes I'd like to see addressed, but they don't have to be addressed in this PR.

return self.nextActionForAvailableConnection(at: index, context: context)
if self.connections.hasActiveConnection(for: connection.eventLoop) {
guard let (index, _) = self.connections.failConnection(connection.id) else {
preconditionFailure("we connection to a connection which we no nothing about")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what this error message is trying to say.


let needRequiredEventLoopConnection =
// 2. or if we have requests for a required event loop
!self.requests.isEmpty(for: eventLoop) &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The performance impact of this phrasing of this check is a bit unfortunate: we search self.requests and self.connections twice. Ideally we'd have a combined check for these so we can iterate these two only once.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true for self.connections but we do not really search self.requests twice because the requests with required event loop and without required event loop live in separate properties inside of self.requests.

@dnadoba dnadoba merged commit 149b8d2 into swift-server:main Nov 2, 2021
@dnadoba dnadoba deleted the dn-http2-state-machine-integration branch November 2, 2021 11:51
@dnadoba dnadoba added the 🔨 semver/patch No public API change. label Nov 3, 2021
@fabianfett fabianfett added this to the HTTP/2 support milestone Nov 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 semver/patch No public API change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants