We concluded Chapter 14 and the distributed key-value store exercise.
Although I was able to solve Parts 1-3, I knew that my solution would run into trouble with Part 4, when replicating the database between nodes for fault tolerance. This is because each replica will return a response, but we only look at one of the messages. So the other responses will stay queued up, and be read the next time we make a request, thus tying together the responses to the wrong request.
We looked at Marlow's solution from the Github repo, and he had a much better way of doing it. Instead of sending every message over to the main untyped channel for the requesting process, generate a separate typed channel per request. Send the "sending" end of that channel along with the original request. Then even if both replicas respond, after we read the response, we close the channel, throwing away the other response.
It's a good general principle to follow when constructing application using distributed-process: any message for which you expect a response should be sent along with its own new channel by which the response will be returned.