Skip to content

Instantly share code, notes, and snippets.

@brett-richardson
Created August 29, 2018 17:58
Show Gist options
  • Save brett-richardson/8f94096ae52fffed44f908e4274e0bb4 to your computer and use it in GitHub Desktop.
Save brett-richardson/8f94096ae52fffed44f908e4274e0bb4 to your computer and use it in GitHub Desktop.
Volluma Room Server
defmodule Volluma.RoomServer do
@moduledoc """
This GenServer manages the lifecycle of a room and acts as the central spoke for other servers
to attach to.
"""
use GenServer
require Logger
alias Volluma.Model.{Room, Membership, User}
alias Volluma.{MembershipsSupervisor, CellsSupervisor}
import GenServer, only: [call: 2]
# Public API
def get_room(pid), do: call(pid, :get_room)
def add_user(pid, user = %User{}), do: call(pid, {:add_user, user})
# Handles
def handle_call(:get_room, _from, state = %Room{}), do: {:reply, {:ok, state}, state}
def handle_call({:add_user, user = %User{}}, _from, state_room = %Room{}) do
Logger.info "Adding user #{user.id} to room #{state_room.id}."
{:ok, membership = %Membership{}} = MembershipsSupervisor.add_user(
state_room.memberships_pid, user, state_room
)
new_state = %Room{state_room |
memberships: state_room.memberships |> MapSet.put(membership)
}
{:reply, {:ok, membership}, new_state}
end
# Callbacks
def start_link(room = %Room{}) do
pid = case GenServer.start_link(__MODULE__, room, name: name(room)) do
{:ok, pid} ->
Logger.info "Started room server for #{room} at #{inspect pid}"
pid
{:error, {:already_started, pid}} ->
Logger.info "Found existing room server for #{room} at #{inspect pid}"
pid
end
{:ok, pid}
end
def init(room) do
{:ok, supervisor_pid} = Supervisor.start_link(children(room), strategy: :one_for_one)
new_room = %Room{room |
pid: self,
cells_pid: find_pid_by_name("#{CellsSupervisor}:#{room.id}"),
memberships_pid: find_pid_by_name("#{MembershipsSupervisor}:#{room.id}")
}
{:ok, new_room}
end
# Private
defp children(room = %Room{}) do
[CellsSupervisor, MembershipsSupervisor] |> Enum.map(fn(module) ->
%{id: "#{module}:#{room.id}", start: {module, :start_link, [room]}}
end)
end
defp find_pid_by_name(name), do: name |> String.to_atom |> Process.whereis
defp name(room), do: String.to_atom "#{__MODULE__}:#{room.id}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment