-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Overview
Follow-up thoughts on some of the notes in the original HackMD file. I think you can make a convoluted case that this is kinda-sorta two-phase commit (2PC), but it's more an exercise in mental gymnastics something truly useful.
Instead, here is what I think the channel invariants are. As we progress on this work, I want us to keep a close eye on these, and be very deliberate about any changes we make to this list. It's essential that we have a clear understanding of the precise guarantees offered by channels, or they're going to make distributed systems harder to write, not easier!
Invariants
Ordering
To begin, channels should inherit the ordering invariants from Go's chan type. There are four invariants (identified by the italic typesetting):
- A send on a channel is synchronized before the completion of the corresponding receive from that channel.
- The closing of a channel is synchronized before a receive that returns a zero value because the channel is closed.
- A receive from an unbuffered channel is synchronized before the completion of the corresponding send on that channel.
- The kth receive on a channel with capacity C is synchronized before the completion of the k+Cth send from that channel completes.
I recommend reading the entire section (its short), as you'll ultimately be writing unit tests that directly assert these invariants.
We also have a Peek operation, so let's define ordering invariants on that:
- For the purposes of synchronization, a peek on a channel is treated as a receive.
Error Handling
Additionally, and because operations in distributed systems can fail, we have a set of error-handling invariants:
- Memory allocation errors on one side of a send-recv pair are not observed by the other.
- A send, receive, peek or close is synchronized before the RPC results are written.
- A canceled receive is not observed by a send.
N.B.: despite outward appearances, item 2 is an error-handling invariant because it implies that network errors are not considered when synchronizing channel operations. Put plainly: if you're sending a value and your connection suddenly drops, a consumer MAY (or may not) have consumed your value.
Note also that the ordering invariants apply to cancelations. Thus, canceled sends are synchronized before any receives (canceled or otherwise), and canceled receives are synchronized before the corresponding send returns. Put plainly: either the sender and receiver both succeed, or they both fail (barring network errors).
Conclusion
I want to stress that we need to actually think about these invariants, and not leave anything to chance. I encourage everyone (or indeed anyone) to raise any questions they may have, and to challenge any part of the above proposition that seems dubious.