Skip to content
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

[BREAKING]: Remove client support for pipelined requests #783

Merged
merged 8 commits into from
Dec 14, 2021

Conversation

quinnj
Copy link
Member

@quinnj quinnj commented Dec 3, 2021

Follows up on the discussion and work started in
#732.

The gist is this: supporting "pipelined requests" is not well-supported
across the web these days and severely complicates the threadsafe client
implementation in HTTP.jl. And as has been pointed out in various
discussions, the attempt to support pipelining is affecting our ability
to avoid thread-safety issues in general (see
#517).

This commit has a few key pieces:

  • Splits "connection pooling" logic into a new connectionpools.jl file
  • Removes pipeline-related fields/concepts from the ConnectionPool.jl
    file and specifically the Connection/Transaction data structures
  • Attempts to simplify a lot of the work/logic around managing a
    Transaction's lifecycle

Things I haven't done yet:

  • Actually deprecated the pipeline_limit keyword argument
  • Got all tests passing; I think the websockets/server code isn't
    quite ironed out yet, but I'll dig into it some more tomorrow

Big thanks to @nickrobinson251 for help reviewing the connectionpools.jl
logic.

Pinging people to help review: @c42f, @vtjnash, @s2maki, @fredrikekre

Follows up on the discussion and work started in
#732.

The gist is this: supporting "pipelined requests" is not well-supported
across the web these days and severely complicates the threadsafe client
implementation in HTTP.jl. And as has been pointed out in various
discussions, the attempt to support pipelining is affecting our ability
to avoid thread-safety issues in general (see
#517).

This commit has a few key pieces:
  * Splits "connection pooling" logic into a new connectionpools.jl file
  * Removes pipeline-related fields/concepts from the ConnectionPool.jl
  file and specifically the `Connection`/`Transaction` data structures
  * Attempts to simplify a lot of the work/logic around managing a
  `Transaction`'s lifecycle

Things I haven't done yet:
  * Actually deprecated the `pipeline_limit` keyword argument
  * Got all tests passing; I think the websockets/server code isn't
  quite ironed out yet, but I'll dig into it some more tomorrow

Big thanks to @nickrobinson251 for help reviewing the connectionpools.jl
logic.

Pinging people to help review: @c42f, @vtjnash, @s2maki, @fredrikekre
@fredrikekre fredrikekre added this to the 1.0 milestone Dec 3, 2021
@quinnj
Copy link
Member Author

quinnj commented Dec 4, 2021

Pushed some more updates; notable I went ahead and removed the Transaction struct all together; without pipelining, I don't think it really makes sense to keep it around, since it was just passing operations through to the underlying Connection anyway. I've also tried to clean up some of hte logic in the StreamsRequest layer.

More tests are passing, but there are still some failures in websocksets and servers, so I'll move on to those next.

@codecov-commenter
Copy link

codecov-commenter commented Dec 7, 2021

Codecov Report

Merging #783 (6ed7c68) into master (01315fb) will decrease coverage by 0.18%.
The diff coverage is 92.17%.

❗ Current head 6ed7c68 differs from pull request most recent head 246916c. Consider uploading reports for the commit 246916c to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master     #783      +/-   ##
==========================================
- Coverage   77.43%   77.25%   -0.19%     
==========================================
  Files          38       39       +1     
  Lines        2562     2493      -69     
==========================================
- Hits         1984     1926      -58     
+ Misses        578      567      -11     
Impacted Files Coverage Δ
src/Streams.jl 96.42% <ø> (ø)
src/connectionpools.jl 89.53% <89.53%> (ø)
src/ConnectionPool.jl 83.07% <92.95%> (+1.47%) ⬆️
src/ConnectionRequest.jl 78.46% <100.00%> (-2.43%) ⬇️
src/HTTP.jl 95.74% <100.00%> (ø)
src/Servers.jl 84.75% <100.00%> (-1.22%) ⬇️
src/StreamRequest.jl 93.22% <100.00%> (-0.90%) ⬇️
src/access_log.jl 90.00% <100.00%> (-3.34%) ⬇️
src/parseutils.jl 56.25% <0.00%> (-18.75%) ⬇️
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 01315fb...246916c. Read the comment docs.

@quinnj
Copy link
Member Author

quinnj commented Dec 8, 2021

Ok, made some good progress today; tests are passing everywhere except windows, so I'll need to dig my windows machine out, blow the dust off, and try to figure out what's going on there. My guess is a slight change in behavior about when connections get closed and how long they stay valid; this comes from finding several issues where connection/transaction lifetimes weren't really being managed properly on current master code.

I had the idea of setting up a google/zoom video call on Friday for anyone interested in doing a thorough walk-through of the changes here; would people be interested in that? @fredrikekre, @christopher-dG, @c42f, @oxinabox, or anyone else?

@fredrikekre fredrikekre mentioned this pull request Dec 8, 2021
12 tasks
@oxinabox
Copy link
Member

oxinabox commented Dec 8, 2021

sure, keen.

Copy link
Contributor

@c42f c42f left a comment

Choose a reason for hiding this comment

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

This seems great!

The concurrent aspects are an enormous amount clearer now, and I think the pool now has a chance of being correct (it's still a bit subtle though, I wouldn't want to bet on it either way 😆)

I've done a thorough review, having looked at this code before. Major points (discussed in depth in inline comments):

  • I think we could simplify the acquire/release further by always passing connections via the buffer of idle connections
  • It seems fundamentally buggy to use hashconn to identify connections via the hash rather than the actual connection key fields. What protects us from hash collisions and sending data to the wrong host?
  • I think sslupgrade can forget to close connections as it acts weirdly outside the cache with an existing connection.
  • Can we drop reuse_limit completely? IIUC curl doesn't have this kind of thing and maybe we don't need it for HTTP clients.

src/ConnectionPool.jl Outdated Show resolved Hide resolved
src/ConnectionPool.jl Show resolved Hide resolved
src/connectionpools.jl Outdated Show resolved Hide resolved
get!(() -> Pod(), pool.conns, x)
end
end
const POOL = Pool(Connection)
Copy link
Contributor

Choose a reason for hiding this comment

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

A side comment (not todo in this PR) — I'd love it if the pool was attached to the HTTP stack instead of being a magic global shared by all stacks behind the scenes. Then people using their own stack wouldn't need global state at all.

(Of course, this means the HTTP stack would need to be a value rather than a type, which is breaking.)

Copy link
Member Author

Choose a reason for hiding this comment

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

I think moving the layer machinery to be based on values instead of types would be good as well. We should make the change for 1.0

Copy link
Member

Choose a reason for hiding this comment

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

Added to the list in #786.

src/ConnectionPool.jl Outdated Show resolved Hide resolved
src/connectionpools.jl Outdated Show resolved Hide resolved
src/connectionpools.jl Show resolved Hide resolved
src/connectionpools.jl Outdated Show resolved Hide resolved
src/HTTP.jl Outdated Show resolved Hide resolved
src/connectionpools.jl Show resolved Hide resolved
* Added `GC.@preserve` annotations
* Removed calls to `hash` in `hashconn` and renamed to `connectionkey`
* Removed enforcement of `reuse_limit`
* Renamed some fields/variables for clarity
* Cleaned up comments for clarification in connectionpools.jl
* Added an additional `acquire` method that accepts an already created
connection object for `Pod` insertion/tracking
@quinnj
Copy link
Member Author

quinnj commented Dec 14, 2021

Ok, just pushed a commit that covers everything @c42f brought up in review.

@quinnj
Copy link
Member Author

quinnj commented Dec 14, 2021

Tests are all passing (except the known failing windows case that I'll look into next #787 ). Does anyone else want to review? Happy to wait. I'm also still happy to setup a walk-through call if anyone is interested and can give me a date and time that would work for them. My schedule is pretty flexible this week, so basically any time.

@quinnj
Copy link
Member Author

quinnj commented Dec 14, 2021

If no other comments/review arise, I plan on merging this in about 12 hours. Then we can push on other 1.0 issues to try and get that out soonish as to not keep the master branch in too weird of a non-released state.

@quinnj quinnj merged commit f3a3fb7 into master Dec 14, 2021
@quinnj quinnj deleted the jq/pas_de_pipe branch December 14, 2021 18:39
This was referenced Mar 16, 2022
@quinnj quinnj changed the title Remove client support for pipelined requests [BREAKING]: Remove client support for pipelined requests Jun 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants