I’ve implemented my first GenServer and Supervisor, here is the code
defmodule Spare.DataCenter do
use GenServer
#Client
def start_link(_opts \\ []) do
GenServer.start_link(__MODULE__, [
{:ets_table_name, :link_cache_table},
{:log_limit, 1_000_000}
], name: :data_center)
end
def add_question(question) do
GenServer.cast(:data_center, question)
end
def view_questions() do
GenServer.call(:data_center, :view_questions)
end
def get_question(question) do
GenServer.call(:data_center, {:view_questions, question})
end
def remove_question(question) do
GenServer.cast(:data_center, {:remove_question, question})
end
#Server
def init(args) do
[{:ets_table_name, ets_table_name}, {:log_limit, log_limit}] = args
:ets.new(ets_table_name, [:named_table, :set, :protected])
{:ok, %{log_limit: log_limit, ets_table_name: ets_table_name}}
end
def handle_cast({:remove_question, question}, state) do
%{ets_table_name: ets_table_name} = state
:ets.delete(ets_table_name, question)
{:noreply, state}
end
def handle_cast(question, state) do
%{ets_table_name: ets_table_name} = state
:ets.insert_new(ets_table_name, question)
{:noreply, state}
end
def handle_call(:view_questions, _from, state) do
%{ets_table_name: ets_table_name} = state
questions_list = :ets.tab2list(ets_table_name)
{:reply, questions_list, state}
end
def handle_call({:get_question, question}, _from, state) do
%{ets_table_name: ets_table_name} = state
questions = :ets.lookup(ets_table_name, question)
{:reply, questions, state}
end
end
defmodule Spare.DataCenter.Supervisor do
use Supervisor
def start_link(_opts \\ [], _any \\ []) do
Supervisor.start_link(__MODULE__, :ok, name: :data_center)
end
def init(:ok) do
children = [
worker(Spare.DataCenter, [[name: :data_center]])
]
supervise(children, strategy: :one_for_one)
end
end
and I added my Supervisor to the Application children like this
def start(_type, _args) do
# List all child processes to be supervised
children = [
# Start the Ecto repository
Spare.Repo,
# Start the endpoint when the application starts
SpareWeb.Endpoint,
# Starts a worker by calling: Spare.Worker.start_link(arg)
# {Spare.Worker, arg},
Spare.DataCenter.Supervisor,
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Spare.Supervisor]
Supervisor.start_link(children, opts)
end
However everytime I start my app with iex -S mix
I get the following error;
Generated spare app
** (Mix) Could not start application spare: Spare.Application.start(:normal, []) returned an error: shutdown: failed to start child: Spare.Supervisor
** (EXIT) shutdown: failed to start child: Spare.DataCenter
** (EXIT) already started: #PID<0.352.0>
any help with that?
Thanks in advance.