lib/documents/session/supervisor.ex

defmodule Ravix.Documents.Session.Supervisor do
  @moduledoc """
  Supervisor for RavenDB Sessions
  """
  use DynamicSupervisor

  alias Ravix.Documents.Session
  alias Ravix.Documents.Session.State, as: SessionState

  def init(init_arg) do
    DynamicSupervisor.init(
      strategy: :one_for_one,
      extra_arguments: [init_arg]
    )
  end

  @spec start_link(any) :: :ignore | {:error, any} | {:ok, pid}
  def start_link(store) do
    DynamicSupervisor.start_link(__MODULE__, %{}, name: supervisor_name(store))
  end

  @doc """
  Creates a session with the informed initial state
  """
  @spec create_session(SessionState.t()) :: :ignore | {:error, any} | {:ok, pid} | {:ok, pid, any}
  def create_session(%SessionState{} = session_state) do
    session_state = session_state |> SessionState.update_last_session_call()
    DynamicSupervisor.start_child(supervisor_name(session_state.store), {Session, session_state})
  end

  @doc """
  Closes a session for the informed store using the session pid or session_id
  """
  @spec close_session(atom(), pid | bitstring()) :: :ok | {:error, :not_found}
  def close_session(store, pid) when is_pid(pid) do
    DynamicSupervisor.terminate_child(supervisor_name(store), pid)
  end

  def close_session(store, session_id) do
    case Registry.lookup(:sessions, session_id) do
      [] ->
        {:error, :not_found}

      sessions ->
        {pid, _} = sessions |> Enum.at(0)
        DynamicSupervisor.terminate_child(supervisor_name(store), pid)
    end
  end

  defp supervisor_name(store) do
    :"#{store}.Sessions"
  end
end