Rethink inputClosed and CloseModes
After having implemented my own channels one thing that was quite confusing was how to handle half closures. To quickly summarize my learnings:
-
ChannelEvent.inputClosedshould only be handled if the channel optionAllowHalfRemoteClosureis set. Furthermore, the event must be ordered w.r.t. reads since we consider it part of the data stream - CloseMode.output is similar in the way that it should be ordered with the writes since it is part of the data stream as well
- CloseMode.input is a bit of a weird one and a lot channels don’t support it or just escalate it to full closure
- CloseMode.all just leads to full closure in a lot of cases unless the protocol has a concept of closing then it might want sent out some frames first and then close
All in all, this was not super obvious to me when trying to implement the correct behavior myself. If we do a NIO3 we should revisit this and see if we can come up with a model that is easier to understand from a user perspective.
- Furthermore, the event must be ordered w.r.t. reads since we consider it part of the data stream
@FranzBusch are you saying reads are not ordered correctly with input closed events. It was never obvious to me as from a channel handler's point of view these are received from different sources. Similarly are writes flushed before a channel is closed?
- CloseMode.input is a bit of a weird one and a lot channels don’t support it or just escalate it to full closure
Are there are any channel types that allow you to close input but not output?
@FranzBusch are you saying reads are not ordered correctly with input closed events. It was never obvious to me as from a channel handler's point of view these are received from different sources. Similarly are writes flushed before a channel is closed?
Reads should be ordered correctly with input closed but that correct ordering is up to the Channels to get right. That means every channel implementation that supports input closed needs to buffer these events w.r.t the order of reads. That just brings a larger burden onto channel implementors and at best it would be more obvious from an API design that inputClosed is associated with the read data flow. (same applies for CloseMode.output)
Are there are any channel types that allow you to close input but not output?
This is not only a question for channels but also channel handlers that implement protocols. Some protocols support half-closure and those will support CloseMode.output e.g. TCP. However, from the list of channels and handlers that I know, I think all of them escalate CloseMode.input to full closure or they just fail the promise with unsupportedOperation.
hmm