docker / libchan

Like Go channels over the network
Apache License 2.0
2.47k stars 142 forks source link

Add channel select capability #76

Open stevvooe opened 9 years ago

stevvooe commented 9 years ago

Most of the power of Go channels come from flexibility provided by select clauses and the analogous reflect package API. An efficient select functionality in libchan would bring it further into parity with Go channels and could support some powerful use cases:

  1. A select server where different request types are sent over different channels. The server blocks on all channels until one can proceed and it handles the specific request type (See https://github.com/docker/libchan/issues/73#issuecomment-65455811 for a more detail description).
  2. Provide synchronization of distributed request control flow (lots of words). Imagine propagating a timeout through a pipeline of processes, using an operation channel and a cancellation channel.

An implementation could be as simple as providing a select call that spawns multiple goroutines for each sender and receiver passed in and dispatches a callback based on it. More complex implementations would add methods to Sender and Receiver that indicate whether the operation can proceed. It may make sense to even bridge it with process-local Go channels. The API could take hints from the reflect package channel API.

dmcgowan commented 9 years ago

My thoughts on this and general synchronization is mostly about how acks would need to work. To get normal channel behavior (without select), a single ack is needed to be sent by the receiver to allow the sender to unblock. To implement channels with select, a double ack would be needed to unblock the sender, and then the receiver. I think it would be worth exploring if this pattern can be achieved without changing the underlying protocol, and if not, whether the underlying protocol can be changed without changing the core interface. Changing the core interface is not an option, but adding tools, utilities, and better constructors is certainly worth exploring. Can you also come up with a more concrete example? Otherwise I will tag and just let sit.

tve commented 9 years ago

I must be missing something. Isn't the double ack only necessary for channels with capacity 0? Also, t's not really double-ack, just that the receiver has to send a request-for-message and then receives the message in the reply... Sounds very inefficient over a network, doesn't seem like a good network pattern...

mcollina commented 9 years ago

This is really similar to how errors need to be forwarded through Channel. If there are tree parties connected by channels, where A is the sender, B is a generic proxy and C is the actual service:

A --> B --> C
^           |
|-----------|

(sorry for the bad ASCII art)

ACKs will be needed to send over any network error B is facing when contacting C. The current semantic for messages over channels is 'fire and forget'.

@tve anything that we want to guarantee at single process level needs to work with an unlimited numbers of parties involved.

To me @dmcgowan is describing sounds a lot like the 'best effort', 'at least once', and 'at most once' messaging guarantees. A really nice way of describing it is defined in the MQTT 3.1.1 spec QoS section.