Packages

Neo4j driver for Elixir, using the fast Bolt protocol

Current section

Files

Jump to
boltx lib bolt_sips routing connection_supervisor.ex
Raw

lib/bolt_sips/routing/connection_supervisor.ex

defmodule Bolt.Sips.ConnectionSupervisor do
@moduledoc false
use DynamicSupervisor
alias Bolt.Sips.Protocol
alias Bolt.Sips
require Logger
@name __MODULE__
def start_link(init_args) do
DynamicSupervisor.start_link(__MODULE__, init_args, name: @name)
end
@impl true
def init(_args) do
DynamicSupervisor.init(strategy: :one_for_one)
end
@doc """
the resulting connection name i.e. "write@localhost:7687" will be used to spawn new
DBConnection processes, and for finding available connections
"""
def start_child(role, url, config) do
prefix = Keyword.get(config, :prefix, :default)
connection_name = "#{prefix}_#{role}@#{url}"
role_config =
config
|> Keyword.put(:role, role)
|> Keyword.put(:name, via_tuple(connection_name))
spec = %{
id: connection_name,
start: {DBConnection, :start_link, [Protocol, role_config]},
type: :worker,
restart: :transient,
shutdown: 500
}
# [Protocol, role_config];
with {:error, :not_found} <- find_connection(connection_name),
{:ok, _pid} = r <- DynamicSupervisor.start_child(@name, spec) do
[spec, r]
r
else
{:ok, pid, _info} -> {:ok, pid}
{:error, {:already_started, pid}} -> {:ok, pid}
pid -> {:ok, pid}
end
end
@spec find_connection(atom, String.t(), atom) :: {:error, :not_found} | {:ok, pid()}
def find_connection(role, url, prefix), do: find_connection("#{prefix}_#{role}@#{url}")
@spec find_connection(any()) :: {:error, :not_found} | {:ok, pid()}
def find_connection(name) do
case Registry.lookup(Sips.registry_name(), name) do
[{pid, _}] -> {:ok, pid}
_ -> {:error, :not_found}
end
end
@spec terminate_connection(atom, String.t(), atom) :: {:error, :not_found} | {:ok, pid()}
def terminate_connection(role, url, prefix \\ :default) do
with {:ok, pid} = r <- find_connection(role, url, prefix),
true <- Process.exit(pid, :normal) do
connections()
r
end
end
def connections() do
_connections()
|> Enum.map(fn pid ->
Sips.registry_name()
|> Registry.keys(pid)
|> List.first()
end)
end
defp _connections() do
__MODULE__
|> DynamicSupervisor.which_children()
|> Enum.filter(fn {_, pid, _type, modules} ->
case {pid, modules} do
{:restarting, _} -> false
{_pid, _} -> true
end
end)
|> Enum.map(fn {_, pid, _, _} ->
pid
end)
end
def via_tuple(name) do
{:via, Registry, {Bolt.Sips.registry_name(), name}}
end
end