Functional Web Development with Elixir, OTP, and Phoenix by Lance Halvorsen

Functional Web Development with Elixir, OTP, and Phoenix by Lance Halvorsen

Author:Lance Halvorsen
Language: eng
Format: epub
Tags: Pragmatic Bookshelf
Publisher: Pragmatic Bookshelf


Naming GenServer Processes

This whole chapter we’ve been starting new GenServer processes and binding their PIDs to variables. Whenever we’ve needed to call a public function on a process, we’ve passed that variable in as the first argument. That clearly works, but it leaves us with a problem.

In a full application, we’d need to keep track of every variable for every process we started. We’d need to always keep them in scope, and we’d need to clear individual variables out when their process stopped. If that sounds really messy, it is.

It would be great if we could just name each process as we start it, and pass that name in whenever we wanted to call a function. It would be even better if we didn’t have to remember the name, but were able to reconstruct it on the fly when we needed to. If wishes came true, these names would clear themselves out when their process stopped.

Wishes can come true. Process registration will do all of this for us.

There are several ways to register GenServer processes by name. Let’s explore them and see which best fits our needs.

The first thing we can do is simply specify a name as an atom as the third argument to GenServer.start_link/3. Let’s open up a new console to test that out:

​ iex> alias IslandsEngine.Game

​ IslandsEngine.Game

​ iex> GenServer.start_link(Game, ​"​​Frank"​, ​name:​ ​:islands_game​)

​ {​:ok​, ​#PID<0.90.0>}​

We are fine using the raw GenServer.start_link/3 function here. We need to specify the module name instead of using __MODULE__ because this function call is not originating inside the Game module the way it is in IslandsEngine.Game.start_link/1.

The part to watch is the keyword list we specified as the third argument, name: :islands_game. This clearly works. We get {:ok, #PID<0.90.0>} as the return value.

Now we can use the atom :islands_game instead of a PID whenever we call client functions in the Game module:

​ iex> ​:sys​.get_state(​:islands_game​)

​ %{​player1:​ %{​board:​ %{},

​ ​guesses:​ %IslandsEngine.Guesses{​hits:​ ​#MapSet<[]>, misses: #MapSet<[]>},​

​ ​name:​ ​"​​Frank"​},

​ ​player2:​ %{​board:​ %{},

​ ​guesses:​ %IslandsEngine.Guesses{​hits:​ ​#MapSet<[]>, misses: #MapSet<[]>},​

​ ​name:​ nil},

​ ​rules:​ %IslandsEngine.Rules{​player1:​ ​:islands_not_set​,

​ ​player2:​ ​:islands_not_set​, ​state:​ ​:initialized​}}

The atom has a direct one-to-one mapping to the PID of a single game process. If we try to start another one with the same atom for the name, we get an error saying that the server is already running:

​ iex> GenServer.start_link(Game, ​"​​Frank"​, ​name:​ ​:islands_game​)

​ {​:error​, {​:already_started​, ​#PID<0.90.0>}}​

Using Process Registration to Our Advantage



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.