Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I'm working on supporting HTTP/2 over unix sockets in Ember and was experiencing a lot of strange issues e.g. non-deterministic behavior, reads returning empty chunks, hanging.
The bad news was that I was unable to replicate these issues as unit tests 🤔 this is where I started from, focused on just the empty read issue, before I gave up and went for the refactor.
The good news is that I published a snapshot and (spoiler alert) was surprised to discover that this refactor somehow fixed everything 😅 wasn't really expecting that.
This refactor mostly addresses these three issues:
Not switching the sockets to non-blocking mode. I suspect that this was what was causing the empty reads bug in Ember. Non-blocking mode is only useful if you are using a selector to poll for events on the socket. Otherwise, you have no way of knowing when there are bytes available on the socket, so you may get empty reads / no-op writes, and be forced to degrade to a busy-loop, which is much worse than doing a blocking read (or write) to begin with.
Note that when the Cats Effect polling system stuff lands, we will be able to register the JDK unix sockets with the polling system and thus have non-blocking reads/writes, so that's something to look forward to.
Carefully wrapping a socket in a resource as soon as it is opened, so that it is guaranteed to be closed in all instances. Attempting to tack on other side-effects as part of the
acquire
phase (e.g., binding or connecting) may lead to a resource leak if those actions fail, because then the socket is never returned, which means it can never be closed, etc.Properly suspending side-effects e.g. interactions with
ByteBuffers
,blocking
, etc.