Elixir. Process Registry. Sockets and gproc.

Distributed Systems Development A-Z Guide.

Dmytro Nasyrov
Pharos Production
4 min readJun 15, 2017

--

That one on top of the supervision tree!

Give us a message if you’re interested in Blockchain and FinTech software development or just say Hi at Pharos Production Inc.

Or follow us on Youtube to know more about Software Architecture, Distributed Systems, Blockchain, High-load Systems, Microservices, and Enterprise Design Patterns.

Pharos Production Youtube channel

Last time we have looked at process registry with ETS lookup. That was freaky cool but what should we do with all that stuff? Let make it more interesting. This time we will use a process registry to run socket worker. The app will listen to a socket(only one for the sake of simplicity) and respond with a dummy message.

Sockets

Take a look at observer screenshot. On the top of the supervision tree, there is a tiny process — our listener. It was started by an application supervisor and now listens to incoming connections.

Let’s add two new packages to compile-time dependencies — :gporc and :socket. You can find more on the screenshot but we will talk about them in future articles.

Compilation time deps

Gen_server

Let’s replace our Process Registry on to battle-tested erlang’s library called Gproc. All we should do is to change via tuple. Else is the same. :n — means name, :l — means local. Every process will be registered locally on a node with a unique name.

Gen_server

Application

Application module starts socket listener in a supervision tree. Simple enough. We pass only one parameter — port. Surely port should be passed in some other less stupid way, but this time we add it through initialization parameters for the sake of clarity.

Application supervision tree

Socket Listener

Socket listener API

Socket listener is not a gen_server as you have been expected. But it has similar API to make it possible to use from a supervision tree. For now, we have only one function — start_link with a port parameter. Start_link spawns a new linked process. We have seen it in application supervisor. This is a dedicated process which listens to the port. Socket sits on top of inet application, you can find extensive documentation here inet

Listen to that TCP connection I say!

We start an infinite loop in the init. When a connection is established we spawn a new process with a worker inside and back to listen to the next connection.

That’s how should we start a worker

Now the most interesting part of the module. We should listen to messages and send them to a worker.

Listener part

We have Socket receive case handler. In case of nil we pass through the function. In case of closed and halted connections we can skip and return just :ok atom, we don’t care for now. When we receive data we send a cast message to the worker. We send cast because we don’t care about the return value, it will be returned by a socket library. We send a cast message to a process which is registered globally via :gproc. :l — means locally on the node, :p — means property and let us set key/value pair for a process, other processes can set a name and value on their own.

Socket Worker

Socket worker

Start_link has been started by a Socket Listener. In init callback, we register a new process under :socket_listener atom with :p and :l keys. When worker receiving cast messages it can return values asynchronously by Socket library. That’s it!

Let’s Try!

Let’s run one terminal with a listener.

Listener

And another terminal with a telnet connection. As you can see our listener has started a new worker! Cool!

Socket listener starting a worker
Telnet connection

When we send a message to the application we can see it now! Socket listener works as it should.

Message from a telnet connection.

DONE

Link to Github repo pharosproduction/process-registry

Thanks for reading!

--

--

Dmytro Nasyrov
Pharos Production

We build high-load software. Pharos Production founder and CTO.