How to set the GenServer State on fly using :sys module — Elixir/Erlang

Be dynamic to be historic.

Photo by Annie Spratt on Unsplash

This article guides you to set the state of the GenServer on fly using iex

Hello everyone!

No excuse for a programmer to learn something new always. 
OK! Thoughts are apart. Let’s code.

Why would some one set the state onfly?

You may have your own reasons. In my case, I forgot add reset action to my GenServer and pushed the code to production grade level.

Now, the server has gone live. To the client need, now I have to reset the state of the server. OK! Let’s make our client happy :)

Demo GenServer

To save our time, I have come up with a simple GenServer code for the demo. It just maintains the state of an employee salary.

Let’s write our server. 
Create a file demo_server.ex using your favorite editor.

$ vim demo_server.ex

Copy the following code and write to the file you have created before demo_server.ex

defmodule DemoServer do
use GenServer
  @vsn 1  
## Client API
  def start_link employee do
GenServer.start_link __MODULE__, employee, []
end

def add_money(pid, value) do
GenServer.call(pid, {:add, value})
end
  ## Server API
def init(employee) do # initiating state with passed employee details
{:ok, employee}
end

# add the value to the state and returns :ok
def handle_call({:add, value},_from, %{name: name, money: money} = state) do
{:reply, "#{value} added to #{name} ", Map.put(state, :money, money+value)}
end

end

Now, open the iex and load the file.

$ iex
iex> c "demo_server.ex" 
iex> {:ok, pid} = DemoServer.start_link(%{name: "blackode", money: 25000})
iex> DemoServer.add_money, pid, 5000
"5000 added to blackode"

You shall need to be in the same directory of where the demo_server.ex lies. Purposely, I did not write any get handlers here to show you the another way of getting the state using pid.

Now, how do we get the state?

iex> :sys.get_state(pid)
%{name: "blackode", money: 30000}
# here pid is the process identifier of demo_server
iex> DemoServer.add_money(5000)
"5000 added to blackode"
ex> :sys.get_state(pid)
%{name: "blackode", money: 35000}

Now, the client asks you to reset the salary to 0 But, we don’t have the function to call that satisfy the client.

We can still use :sys.replace_state/2 function to replace the state with new_state.

iex> :sys.replace_state pid, fn state -> %{state | money: 0}
%{money: 0, name: "blackode"}
iex> :sys.get_state pid
%{money: 0, name: "blackode"}

I took a silly reason to show you the demo. My only intention is to introduce :sys erlang module. You can use this module to the greater extent once you know how to use it.

Live demo

Hope You liked it!

Thanks for reading.

Join Our Telegram Channel and support us.

https://t.me/blackoders
if worth_clapping, do: “clap”, else: nil

Happy Coding 🎉