Add a pipeline builder that checks the validity of the order of handlers #2335
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.
Add a pipeline builder that checks the order of handlers
Motivation:
While NIO's pipelines provide an exceptionally good framework for networking, there are two main outstanding imperfections in NIO's pipelines that are yet to be improved upon.
First of all, channels depend on NIOAny for unwrapping types, the pipeline handlers types are therefore not checked at compile time, leading to headaches - in particular when working with more complex Channel setups.
In addition to the above, channels require a fair amount of 'extra' calls to glue handlers together. After a handler received a read or write, it applies any logic, and writes their 'Out' type into the next handler in line. To call the next handler, handlers need to invoke a read/write on a 'Context' type which has knowledge of the pipeline. This context then calls the next handler with the same payload. This is suboptimal for the performance of NIO based networking.
While this PR doesn't fix either of those, it _does_reduce the headaches originating from a lack of type-checking. This PR would pave the way for the above two changes to be made in follow-up PRs. Not only does this improve the performance of SwiftNIO. It also improves the maintainability of SwiftNIO based applications significantly, while lowering the entry-barrier for newer network application developers.
Another future direction I can see this leading towards, is the addition of groups of handlers (as Johannes called them 'Fuses'). A 'fuse' could represent an HTTP1 or HTTP2 pipeline. From that change onwards, an HTTPS server would simply add the TLS + SNI handlers on a pipeline. Following the result of SNI, either the HTTP1 or the HTTP2 fuse would be appended to the pipeline, from then on handling the decrypted traffic.
Modifications:
This PR introduces a new ChannelPipelineBuilder, a result builder that uses buildPartialBlock's reducer pattern to check Inbound and Outbound types in both directions. This resultBuilder contains a special case allowing
IOData
andByteBuffer
to be used interchangeably.Result:
After these changes, the result builder can be leverages to create a pipeline that is type checked. Immediately following the merge of this change, this will increase maintainability of NIO's pipelines.
This could in future versions lead to the elimination of the extra 'glue' calls within NIO itself. In addition to the above, it can be leveraged to provide APIs on Channels that are aware of the type(s) that can be written to a Channel, based on the type information available from this resultBuilder.