-
Notifications
You must be signed in to change notification settings - Fork 603
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
Shared server sockets #2300
base: main
Are you sure you want to change the base?
Shared server sockets #2300
Conversation
@RaasAhsan What's that status of this one? |
Sorry for dropping the ball on this (I've been a bit busy), but I think it's ready for a deeper review. It does deserve some tests which I'll try to get to ASAP, but I'm curious to hear thoughts on general approach. I wonder if it's worth exploring a more |
@mpilquist @RaasAhsan I was actually looking at the |
@TimWSpence I need to take a deeper look at this PR, but you may be interested in the change I just made in 9e6a59b. In fact I have some crazy idea that it fixed this :P but yeah, let me actually read about the issue first 😂 |
Oh interesting! Is there a parent issue or PR for some conext on that change? |
Yes, it's part of #3063. |
@armanbilge thinking about it a bit more, a reference-counted resource wrapper like this might be quite useful generally in cats effect. What do you think? |
@armanbilge I don't think your change does fix this - we still have https://github.com/typelevel/fs2/pull/3063/files#diff-f11c9120aaf385f6214d8d1a82560c137b058a244c84ad7d8b7126e78b2081aeL128 which means that the lifecycle of the connection is tied to that of the outer server stream |
@TimWSpence perhaps I misunderstood the original problem. I'm going on #2289:
I'm pretty sure the changes I made make those lifecycles disjoint: the server now accepts sockets into a |
Oh sorry, yeah I missed that those resources are tied to the |
Well, maybe that's not really the problem 😂 see subsequent comment in #2289 (comment). I'm not sure if FS2 actually needs any changes. I suspect we can do this http4s, maybe with some strategic use of |
🤦 how did I miss that. Nice, I'll poke at http4s a bit and see what I can come up with |
Intends to fix #2289. Relevant Gitter conversation located here: https://gitter.im/functional-streams-for-scala/fs2?at=6035dec142f30f75c7c35746
So, the idea here is that the lifecycles of server sockets and client sockets have independent lifecycles, so it should be possible for us to finalize them separately. This was possible to do in 2.5.x because the
SocketGroup
server signature returned aStream[F, Resource[F, Socket[F]]]
, in conjunction with theforking
combinator that was developed in Ember.Unfortunately, that method is leaky (what happens if you don't call
use
on the inner resource?), so the signature changed toStream[F, Socket[F]]
, where the sockets are actually bound to the server stream.parJoin
is necessary here in order to lease the scope and prevent the socket from immediately finalizing, but this sneakily also leases the server socket, preventing that from finalizing until all client sockets have finalized!One solution to maintaining independent resource lifecycles while preserving safety is to implement a data structure called
Shared
that can facilitate the transfer of ownership of resources, which is captured in this PR. A client socket can be allocated on the server stream into a shared resource and handed off to the client stream which will acquire the resource. After that, the server socket can release the resource before moving onto accepting the next socket (this won't actually happen when usingparJoin
because of leasing).I think the
forking
function is going to have change a bit; it'll have to operate on aStream[F, Stream[F, Shared[F, O]]]
because we need to ensure that the shared socket is acquired before control is returned to the accept stream. If it doesn't, the accepted socket is going to be immediately finalized after return. See: https://github.com/http4s/http4s/blob/main/ember-server/src/main/scala/org/http4s/ember/server/internal/StreamForking.scala#L71 . In comparison toparJoin
, the new definition offorking
replaces the notion of implicit scope leasing with the notion of explicit resource transfer.Notes:
server
signatures are completely safe when used withparJoin
, but I think we can even just revert them to their previous versions, and add a separate signature that exposesShared
.forking
in fs2 that people can use to exercise the graceful shutdown behaviorStream
somehow? Keyword there is safe