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.
Check out the GitHub repository on Killer Elixir Tips
Glad if you can contribute with a ★