Faced with three exams within three days in the first exam week, and three practicum assignments still to complete before I could even start to study for those exams, last week I decided it was time to get at least one of those things out of the way, and quickly. The obvious choice was the final assignment for distributed systems, because it looked comparatively small and doable. So after we had successfully handed in the solution to the third assignment (the last but one) for the architecture practicum, I told my programming partner I would do this, all alone, in exchange for his completing the final assignment for architecture. What I didn’t tell him was that I had the firm intention of getting this done over the weekend and hand it in before Christmas.
What spurred me on was that my partner from the process mining practicum and two other co-students had the same plan. In fact, right after the architecture practicum we met in a computer pool and starting working on the final assignment (well, I personally first wrote the previous blog post). My practicum partner (process mining) continued to program, test, and debug away over the weekend, as did I, in any free moment. So we chatted away all the time and this really boosted my motivation. If she could do it, I felt, so could I. Even though she’s childless and has as lot more free time.
The final part of assignment number two had been implementing a group election algorithm for a distributed system, and that had been just a few hours of work, with most of that time spent on getting threading to work in Python. Number three was a distributed mutex (mutual exclusion) algorithm: Basically, communicate with everybody else to make sure only one process at a time enters a “critical section”. This was obviously more complex in that the mutex was global rather than just for the group, so we had to succeed in communicating with everybody else in the practicum. But it was also, I thought, basically more of the same. So I didn’t expect this to be terribly difficult.
In the end, it was not quite as trivial as I thought, because the logic was a good deal more complex than with elections. You had to handle a complicated choreography of sending requests, processing replies according to a conditional logic, keep track of who had replied, run two sets of timers, inquire after the status of those who hadn’t replied after the first timer ran out, and so on. And getting all of that to work involved the usual debugging of malformatted replies, missing fields in replies, JSON exceptions, thread-safe collections that still refused to be written to in another thread, and so forth. Not to mention that the entire thing depended on the correct handling of logical clocks (basically, counters of actions kept and synchronized between all those participating).
Still, it was mainly about logic, not technology, and conceptually in fact not much more difficult than the election algorithm. And that made it rather relaxing to work on, compared to the previous nightmare with Kubernetes etc. for the architecture practicum. Basically I had a good time leisurely programming function after function in Python, within the structure of a software that by then was thoroughly familiar to me. It was like building a minor addition to a house with lego bricks: one brick after another.
In the end the major challenge was really the non-responsive services that the others were programming at the same time. Too many claimed the mutex capability in their clients but did not actually respond when inquired, or their replies were malformed. I tried to compensate for the most obvious omissions, like URLs without the schema prefix (http://), but that didn’t save me from having to deal with those who simply didn’t reply at all, as the algorithm required us to wait for all those who didn’t give their explicit OK. In the end, however, some time Sunday night, after a lot of debugging and digging through thousands of log lines, I found, with some surprise, that my mutex seemed to work. Except maybe for the logical clocks.
Originally I had mixed feelings about trying to hand in early. The actual deadline is in the new year, i.e. we have to hand in at the final practicum meeting in the second week of January. It seemed attractive to get rid of this assignment, but being very early might induce the assistant to be very critical of our work. You know, as in “don’t be so hasty, you still have plenty of time to get this right.” And it was, after all, a sloppy piece of spaghetti code, even after this morning I took an hour or so during the project course meeting (yeah, mea culpa) to get the logical clocks right.
But what compelled me to at least try, anyway, was the intuition that the longer we waited, the more other students would implement their own mutexes and thus force us to handle their responses, or lack thereof. Whereas today we could hope to get away with dealing just with two of our own clients and a few who had forgotten to delete their own services even though they were unresponsive but did indicate, permanently, that they competed for the mutex.
So we left our project course meeting a bit early to catch the assistant at the end of the project course he is teaching. The co-students mentioned earlier had tipped us off that he was prepared to accept solutions for distributed system assignments at that time and place, even though they had nothing to do with his project course.
And it was a breeze. We talked him through our code and through the many pages of logs a simple mutex request produced in our service, and apparently by doing so we demonstrated sufficient understanding of the intricacies of the assignment for him to give us the checkmark, even though for lack of people actually communicating with us many parts of our code remained in fact untested. Which of course had been the idea all along.
Oh, mind you, I am honestly convinced that my code works, but talking with real services written by real people who all have their own understanding of what a mutex or a logical clock or a properly formatted JSON string is, a lot can go wrong. And that’s not a nice thing to watch, even though it might mostly not have been our fault. As it is, we got away with a lot of talking and very little proven functionality. In fact, once done the assistant even allowed us to sign the attendance sheet for the meeting in January. So we don’t even have to show up any more.
And that’s one practicum done entirely, and a major load off my mind. You know, this is the practicum that just three weeks ago caused me to have sleepless nights and trouble breathing. I breathe a lot easier now.
The funny thing is that in the end, after I had felt motivated to work on this assignment primarily because some of my co-students thought they would hand it in this Monday, we were the only ones actually handing this in today. In fact, we were the first ones in the entire practicum, among over 60 people, to submit their solution. And that after we had been a week late with the second assignment. We sure did catch up!
And by the by, that’s me having done at least as much as my practicum partner for assignments one and two, plus assignment three all alone, plus assignment two for architecture and most of assignment three there as well. I can reasonably expect him to keep his word now and complete the final assignment for architecture on his own, leaving me free now to concentrate on the process mining assignment (which my teammate and I plan to complete on Wednesday) and studying for the exams.
How is that for an early Christmas gift?