Part 5: Config

Introduction

This article is pretty straightforward. When we started with adding additional functionality to our code, we began with invocation arguments. This approach, however, is not scalable when you have to deal with more than three or four such arguments. Imagine starting a program with 20 arguments!

To get around this, most projects use something called a “config” file. Using a config file is pretty straightforward - you store the values in a file, read it, parse the values in the file and trigger your program with those values. In this article, we shall explore adding a config file for our project. Once we do that, we shall use it as the source of truth for all configuration options we have.

Part 4: Modularizing

Let’s take a small detour from the distributed systems-focused workflow here to focus on modularizing our code. Right now we have a mammoth main() function that simply becomes spaghetti if we want to add more functionality. Some of the more “standards-enjoyer”-like of y’all might actually prefer limiting your code to 80 characters wide (it’s also a goal that I have tried to maintain for the markdown files in this blog), which you can already see might lead to funky indentations and nearly-unreadable code.

Part 3: Talking and Listening

Introduction

We’ve all been there. It’s ten minutes before the debate competition. In every corner of the waiting room stands a candidate, rehearsing their arguments and making sure that their stance is believable to themselves. The more astute of them however, would go forth and and debate themselves, trying to find those miniscule improvements in semantics that could bolster their defenses against a ruthless interjector.

Now imagine if they were all in the same coordinates (somehow). They would all be talking over each other and not knowing whether they were listening to themselves or another guy who was right there. Now imagine you have multiple applications listening on the same source (port, if you want to be precise). The issue is, you never know which application should parse which message! Of course, the underlying infra in your computer will not allow you to set up two servers (listeners) in the same location, unless you go with SO_REUSEPORT, which is a whole different ball game and lead to errors out of your control.

Part 2: Speaking

Speaking?

In the previous article, we touched upon “listening” - the ability in your distributed system component to accept information from elsewhere on the fly. However, “speaking” - the ability for your distributed system component to send data to other components - is essential if you want to enable complex automation without having to hardcode every scenario. Wihout it, everything is reactive, and you may end up holding connections to too many components, leading to callback hell and extreme resource usage.

Part 1: Listening

Listening?

The first step towards having a distributed system is for a way to make it “listen”. Ideally, your system should be able to branch out its operations by understanding the context in which it is invoked. This includes stuff like input/invocation arguments, communicated entities, internal state, etc. We shall start with these forms of understanding before we move on to more complex means of deducing context.

Input / Invocation Arguments, and why we need active listening

I wouldn’t characterize this as “listening” per se, but rather “knowing in what context one spawns”. We shall talk about this later, when we need to handle multiple “listeners”, but for now, let’s focus on the actual listening that takes place.