Practice meeting, Jan. 6th

2 views
Skip to first unread message

Lyle Kopnicky

unread,
Dec 24, 2019, 11:00:34 PM12/24/19
to pdxfunc
When: Monday, Jan 6th, 6:30-8:30pm

Where: Collective Agency Downtown, Suite 1108, 511 SW 10th Ave, Portland, OR (opposite side of the floor from the elevators)

We'll discuss solutions for the exercises at the end of Chapter 14, "Distributed Programming", of Parallel and Concurrent Programming in Haskell. Please try your hand at the exercise in "Failure and Adding/Removing Nodes" and/or "A Distributed Key-Value Store". At the meeting anyone will be able to present and contribute to the discussion.

Meetup link to RSVP:

Hope to see you then!

Lyle Kopnicky

unread,
Dec 31, 2019, 7:33:37 PM12/31/19
to pdxfunc
Here's my solution for the distributed chat server that allows nodes to join/leave at will:

https://gist.github.com/lylek/f30f6bd4d7a6898511cfa60e30fe71c4

Some lessons I learned:

I was getting some double MsgServerInfo messages. When a new server joins, after getting a WhereIsReply for each peer, it sends a MsgServerInfo to that peer. Then the peer sends back a MsgServerInfo. But then the first server was sending back yet another MsgServerInfo! That third one was getting ignored, because the remote server already knew the sender. But it still seemed like a waste of resources.

I thought at first perhaps I needed to keep track of which servers I had sent MsgServerInfos to. That seemed a bit complex. Then I realized that the message itself could be an indicator of whether it was the original message, or the reply. At first I thought I could have a MsgServerJoin for the original message, and a MsgServerInfo for the reply. But then I realized that I could just use a single data structure but put a flag in it.

When I later looked at the author's solution, it turned out he had done the exact same thing.

When you monitor the remote process, you're in some code that runs in STM. At first, to solve this problem, I tried to push the "monitor" command onto the proxy channel. Well, the "monitor" command ran, but then I was getting no notifications.

At first I thought perhaps the library was broken, and I was looking through the code. I thought maybe it didn't work on the Mac, or when the processes were on separate nodes. Then I remembered that the author's repo had a sample solution. I compiled and ran it. It worked fine. So, not a library problem!

I looked for differences between the author's solution and mine. I saw that he was doing a join right there in the handler for the MsgServerInfo message, in order to execute the command in the Process monad. I thought, but why can't I just as well push it into the proxy channel? I looked at the code handling the proxy channel, and realized that it was spawned as a separate process. So that process was getting the notifications! You can push all sorts of commands off onto the proxy channel, but 'monitor' is not one of them.

So, I followed the author's pattern and did a 'join' right there in the message handler.

--
You received this message because you are subscribed to the Google Groups "pdxfunc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pdxfunc+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pdxfunc/45d3362a-1341-4426-a628-c3bd7e0f6e57%40googlegroups.com.

Lyle Kopnicky

unread,
Jan 6, 2020, 11:57:04 PM1/6/20
to pdxfunc
Good meeting! We discussed the exercise of the distributed chat server with dynamically joining/leaving nodes. Then we went on to discuss the key/value store problem. I had implemented the first part of it, so we looked at that. We talked about what kinds of problems I expect might turn up in the other parts.

We also talked about ordering guarantees in Akka, and how I thought Erlang didn't have those same guarantees, but it turns out it does. And it turns out that the distributed-process library we're using in Haskell also has the ordering guarantee. None of them promise to deliver all messages. But they do promise that between any pair of nodes, any messages sent in a particular order cannot arrive in a different order. This guarantee is helpful for avoiding race conditions.

It can extend to chains of messages along the same path. For example, you can build a binary tree with a separate process for each tree node. You can send a message to the root to get a value. That will then decide whether it can answer the request, or has to send a message to its left child or right child to get the value. Eventually the message will either reach a node that has the value, or a leaf that knows the value is not in the tree. You can also send messages to update the tree, by inserting nodes, or even doing rotations. But then you have to worry about race conditions. The message ordering guarantee helps avoid those race conditions.

Next time we'll try to finish up the rest of the key/value database exercise, and discuss that. If we have time, we'll get into the next (last!) chapter of the book.

- Lyle
Reply all
Reply to author
Forward
0 new messages