First of all I would like to mention that I would have asked this question in the Phoenix forum but unfortunately I do not have access to make a new topic.
I am new to elixir, LiveView and Phoenix and am making a game as a practice project. I am encountering an issue with my GenServer in the mount of my LiveView.
Basically when a new game is generated with a specific uuid, my app redirects to my LiveView and using the uuid that is sent in the params I check if a GenServer Game with the global name containing that uuid is already created or not. If not it starts the GenServer, if it is already created then it simply gets the state of the game.
The issue I am having is that when I refresh the page when the GenServer has already started it should simply get the game and not start a new one.
However what happens is that because the mount is called twice, the first time it properly gets the game but the second time it starts a new GenServer overriding the previous game state.
My LiveView mount
def mount(%{"uuid" => uuid}, _session, socket) do
IO.puts("This is the uuid #{uuid}")
%{current_user: current_user} = socket.assigns
{my_game_state, pid} =
case :global.whereis_name({:name, "Catan.Game.State:#{uuid}"}) do
:undefined ->
# The GenServer is not running, so you can start it
{:ok, pid} = Catan.Game.State.start_link(uuid)
GenServer.call(pid, :get_game)
game_state = GenServer.call(pid, {:join, current_user})
IO.puts("It came into the new game creation block")
{game_state, pid}
pid ->
GenServer.call(pid, :get_game)
game_state = GenServer.call(pid, {:join, current_user})
IO.puts("It came into the continue game block")
{game_state, pid}
end
IO.inspect(my_game_state, label: "This is the game state")
# Other code logic below
end
My GenServer
def start_link(uuid) do
global_name = "Catan.Game.State:#{uuid}"
GenServer.start_link(__MODULE__, [], name: {:global, {:name, global_name}})
end
defstruct [:board, :players, :resources, :cards, :settlements]
@impl true
def init(_elements) do
state = %{
board: BoardMap.board_map(),
players: %{},
turn: 0,
resources: %{brick: 19, ore: 19, sheep: 19, wheat: 19, wood: 19},
# cards: Catan.Game.Card.generate()
settlements: %{}
}
{:ok, state}
end
@impl true
def handle_call(:get_game, _from, state) do
{:reply, state, state}
end
What I get in my terminal window upon refresh is something like this:
This is the uuid
my uuid displayed here
It came into the continue game block
This works properly
This is the game state:
game state displayed here
On second call of mount
This is the uuid
my uuid displayed here (it is same as above so uuid is not changing)
It came into the new game creation block
should not do this as it now creates a new game and overrides the previous state of the game. it should go into the continue case.
This is the game state:
new game state displayed here as it has overridden the previous game
I do not know why this is happening. It should not start a new GenServer upon page refresh. Any help will be greatly appreciated.