Try removing the `InboundCommand`s
The current pipeline structure is pull-based with read and write operations returning futures, so in some ways, they are like a version of a socket that return a Future instead of blocking.
Exception for the InboundCommands: they provide a way for the pipeline to push events, which is a little out of place in the model. That said, they are useful for things like starting up a pipeline in a server where the server itself is the driver.
I think we can do better though, maybe making signaling startup as part of pipeline builders duties or changing what the server uses to bootstrap a pipeline. For example, it seems reasonable to provide a HeadStage[ByteBuffer] to a new form:
type BufferPipelineBuilder = SocketConnection => LeafBuilder[ByteBuffer]
// becomes
type BufferPipelineBuilder = HeadStage[ByteBuffer] => Unit
We'd need to do something to incorporate the info in SocketConnection into HeadStage but that seems like a good idea as well.
This is on hold, if not canceled. @hvesalai has a pretty good point about wanting to be able to propagate cancellation, and without a push-based mechanism, that isn't easy. Inbound commands are becoming advisory commands now, so that addresses some of the difficulty about reasoning. They may be rebranded as InboundEvents instead of InboundCommands to make that more clear.