wip: add target configuration.

This commit is contained in:
James Harton 2024-09-01 17:39:34 +12:00
parent 4d339a270b
commit 6e9ac76dd5
Signed by: james
GPG key ID: 90E82DAA13F624F4
2 changed files with 53 additions and 16 deletions

View file

@ -121,8 +121,6 @@ defmodule Wayfarer.Server do
end
end
@type listener_options :: unquote(Options.option_typespec(Dsl.Listener.schema()))
@doc """
Add a listener to an already running server.
@ -130,8 +128,13 @@ defmodule Wayfarer.Server do
an error, otherwise it will block until the listener is ready to accept
requests.
## Options
The following options are supported by listener configuration:
#{Options.docs(Dsl.Listener.schema())}
"""
@spec add_listener(module, listener_options) :: :ok | {:error, any}
@spec add_listener(module, options) :: :ok | {:error, any}
def add_listener(module, options) do
with {:ok, options} <- Options.validate(options, Dsl.Listener.schema()) do
{:via, Registry, {Wayfarer.Server.Registry, module}}
@ -139,6 +142,26 @@ defmodule Wayfarer.Server do
end
end
@doc """
Add a target to an already running server.
If the target fails to start for any reason, then this function will return an
error, otherwise it will block until the target is started.
## Options
The following options are supported by target configuration:
#{Options.docs(Target.schema())}
"""
@spec add_target(module, options) :: :ok | {:error, any}
def add_target(module, options) do
with {:ok, options} <- Options.validate(options, Dsl.Target.schema()) do
{:via, Registry, {Wayfarer.Server.Registry, module}}
|> GenServer.call({:add_target, options})
end
end
@doc false
@spec target_status_change(
{module, :http | :https, IP.Address.t(), :socket.port_number(),
@ -207,6 +230,10 @@ defmodule Wayfarer.Server do
{:reply, start_listener(listener, state), state}
end
def handle_call({:add_target, target}, _from, state) do
{:reply, start_target(target, state), state}
end
defp start_listeners(listeners, state) do
listeners
|> Enum.reduce_while({:ok, state}, fn listener, success ->
@ -237,23 +264,30 @@ defmodule Wayfarer.Server do
defp start_targets(targets, state) do
targets
|> Enum.reduce_while({:ok, state}, fn target, success ->
target = Keyword.put(target, :module, state.module)
case DynamicSupervisor.start_child(Target.DynamicSupervisor, {Target, target}) do
{:ok, pid} ->
Process.link(pid)
{:cont, success}
{:error, {:already_started, pid}} ->
Process.link(pid)
{:cont, success}
{:error, reason} ->
{:halt, {:error, reason}}
case start_target(target, state) do
{:ok, _} -> {:cont, success}
{:error, reason} -> {:halt, {:error, reason}}
end
end)
end
defp start_target(target, state) do
target = Keyword.put(target, :module, state.module)
case DynamicSupervisor.start_child(Target.DynamicSupervisor, {Target, target}) do
{:ok, pid} ->
Process.link(pid)
{:ok, pid}
{:error, {:already_started, pid}} ->
Process.link(pid)
{:ok, pid}
{:error, reason} ->
{:error, reason}
end
end
defp assert_is_server(module) do
if Spark.implements_behaviour?(module, __MODULE__) do
{:ok, module}

View file

@ -72,6 +72,9 @@ defmodule Wayfarer.Target do
@type key :: {module, :http | :https, IP.Address.t(), :socket.port_number()}
@doc false
def schema, do: @options_schema
@doc false
@spec check_failed({key, reference}) :: :ok
def check_failed({key, id}),