citruz

citruz

LiveView: Created processes die instantly

Hi,
I am trying migrate a small game I wrote to LiveView. However, I am stuck since multiple hours and can’t figure out why the GenServer processes I create seem to die instantly.
I have an Agent module called Global which maintains a Map of Game (GenServer) processes:

defmodule Fakeartist.Global do
    use Agent
...
    def games do
        Agent.get(__MODULE__, &(&1))
    end

    def new_game(player_name, player_id, num_rounds) do
        ...
        {:ok, game} = Game.start_link(player_name, player_id, num_rounds)
        Agent.update(__MODULE__, &Map.put_new(&1, token, game))
        {:ok, token, game}
    end
end

Currently, without LIveView, I do this to create a game inside a controller:

defmodule FakeartistWeb.GameController do
...
    def create(conn, %{"user" => %{"num_rounds" => num_rounds}}) do
        ...
        {:ok, token, _} = Global.new_game(username, get_session(conn, :user_id), num_rounds)
        conn
        |> redirect(to: Routes.game_path(conn, :show, token))
    end
end

It works perfectly, I can retrieve the Game process, call functions on it and so in.
Now I tried to implement the same with LiveViews:
index.html.leex:

<button phx-click="addgame">Create</button>
...
    <%= for  {token, game} <- @games do %>
        <td><%= token %></td>
        <td><%= length(Game.get_players(game)) %></td>
    <% end %>

index.ex:

defmodule FakeartistWeb.GameLive.Index do
...
 @impl true
    def mount(_params, _session, socket) do
      socket = socket
      |> assign(:games, fetch_games())
      {:ok, socket}
    end
  @impl true
    def handle_event("addgame", params, socket) do
      IO.puts("addgame: #{inspect params}")
      {:ok, token, game} = Global.new_game("some_username", "some_user_id", 2)
      IO.puts("addgame: #{inspect Game.props(game)}")
      IO.puts("addgame: #{inspect Global.games[token]}")

      socket = socket 
      |> assign(:games, fetch_games())
      |> push_redirect(to: "/livegame")
      {:noreply, socket}
    end
    defp fetch_games do
      Global.games()
    end

As soon as I click the button, the new Game process is created which can observed in the log:

addgame: %{<...>}
addgame: %{category: :none, current_player: :none, <...>}
addgame: #PID<0.473.0>

This shows the pid and that I am able to call methods on it. However, as soon as the view tries to display the game list, it crashes:

** (stop) exited in: GenServer.call(#PID<0.473.0>, :get_players, 5000)
    ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started

The game was added to the map in Global, but the process that the map entry is referring to and which was still running in the handle_event call seems to have died now.
I have no clue why, is there something I am missing?

I appreciate any help. I tried to reduce the code as much as possible, hope its understandable.

Thanks
Felix

Marked As Solved

ityonemo

ityonemo

You’re missing a whole lot about the lifecycle of processes. For starters, you’re calling Game.start_link inside your liveview, which is unusual. Typically start_link should be called by supervisors, you’ll want your games to be supervised, as supervisors are process lifecycle managers. As your code stands, the lifecycle of your game is directly tied to the lifecycle of your liveview (hence the _link). If your lv dies, so does your game.

Also instead of an agent, you probably want to use a registry to keep track of processes with ids that are meaningful (aren’t pids).

Also Liked

mindok

mindok

No problem with passing round pids per se, but using a registry to lookup processes based on a key that has meaning to your application is so much easier. I found the initial setup a bit of a pain tbh, but in use it makes the code a lot easier to follow. Here’s the “recipe” I ended up with. I’m still missing a couple of pieces - for some reason my registered processes keep running even though the start_link for each “game” is called from a liveview process, but I think I should really have another level of supervision in there as per the supervision tree towards the end of The Erlangelist - To spawn, or not to spawn?.

Anyway…

  1. In application.ex, start a named registry process. The name is an atom that gets used everywhere else:
children = [
      #You use the value assigned to name everywhere else
      {Registry, keys: :unique, name: :game_registry}, 
    ...]
  1. In your Game GenServer module create a via_tuple function that packages your meaningful key into a token that Registry can use to lookup processes. You will need the same name you used in step 1. You can call the function whatever you want, but everyone seems to use via_tuple
  defp via_tuple(game_token) do
    {:via, Registry, {:game_registry, game_token}}
  end
  1. In you create_game function, initialise the process and register with the registry using the token
  def create_game(game_token) do
    GenServer.start_link(__MODULE__, <init args as before>, via_tuple(game_token))
  end
  1. Implement your API functions using the “meaningful” key to look things up
  def do_some_stuff(game_token, stuff_to_do) do
   GenServer.call(via_tuple(game_token), {:do_stuff, stuff_to_do})
  end

Where Next?

Popular in Questions Top

chokchit
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 2733ms. You can configure how long re...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&amp;query=perfume&amp;page=2, I would like to get: ...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 126479 1222
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

We're in Beta

About us Mission Statement