defmodule Pollin.Backend.Memory.EndpointWorker do @moduledoc """ Worker for endpoint """ use GenServer alias Pollin.Resource.Endpoint alias Pollin.Backend.Memory.{CallbackWorker, EndpointSupervisor} @doc false def start_link, do: GenServer.start_link(__MODULE__, [], name: __MODULE__) @doc false def init(_opts) do Process.flag(:trap_exit, true) {:ok, Application.get_env(:pollin, :endpoints) || []} end ## Public API @doc """ List all endpoint """ def index, do: GenServer.call(__MODULE__, {:index}) @doc """ Find endpoint """ def find(id), do: GenServer.call(__MODULE__, {:find, id}) @doc """ Create an endpoint """ def create(%Endpoint{} = endpoint) do GenServer.call(__MODULE__, {:create, endpoint}) EndpointSupervisor.start_callback_worker(:"#{endpoint.id}") end @doc """ Delete an endpoint """ def delete(id), do: GenServer.cast(__MODULE__, {:delete, id}) @doc """ Update an endpoint """ def update(%Endpoint{} = endpoint), do: GenServer.cast(__MODULE__, {:update, endpoint}) ## Private API @doc false def handle_call({:index}, _from, state) do items = state |> Enum.map(fn {_key, endpoint} -> endpoint end) {:reply, items, state} end @doc false def handle_call({:create, endpoint}, _from, state), do: {:reply, :ok, List.insert_at(state, -1, {endpoint.id, endpoint})} @doc false def handle_call({:find, id}, _from, state) do endpoint = case List.keyfind(state, id, 0) do {_, endpoint} -> endpoint nil -> nil end {:reply, endpoint, state} end @doc false def handle_cast({:delete, id}, state) do id = String.to_atom(id) CallbackWorker.reset(id) Supervisor.terminate_child(EndpointSupervisor, id) Supervisor.delete_child(EndpointSupervisor, id) {:noreply, List.keydelete(state, "#{id}", 0)} end @doc false def handle_cast({:update, endpoint}, state) do CallbackWorker.update_endpoint(endpoint) {:noreply, List.keyreplace(state, endpoint.id, 0, {endpoint.id, endpoint})} end @doc false def handle_info({:EXIT, _pid, reason}, state), do: {:stop, reason, state} @doc false def terminate(_reason, state) do Application.put_env(:pollin, :endpoints, state) :ok end end