95 lines
2.8 KiB
Elixir
95 lines
2.8 KiB
Elixir
|
defmodule TakeANumberDeluxe do
|
||
|
alias TakeANumberDeluxe.State
|
||
|
use GenServer
|
||
|
# Client API
|
||
|
|
||
|
@spec start_link(keyword()) :: {:ok, pid()} | {:error, atom()}
|
||
|
def start_link(init_arg) do
|
||
|
GenServer.start_link(__MODULE__, init_arg)
|
||
|
end
|
||
|
|
||
|
@spec report_state(pid()) :: State.t()
|
||
|
def report_state(machine) do
|
||
|
GenServer.call(machine, :report_state)
|
||
|
end
|
||
|
|
||
|
@spec queue_new_number(pid()) :: {:ok, integer()} | {:error, atom()}
|
||
|
def queue_new_number(machine) do
|
||
|
GenServer.call(machine, :queue_new_number)
|
||
|
end
|
||
|
|
||
|
@spec serve_next_queued_number(pid(), integer() | nil) :: {:ok, integer()} | {:error, atom()}
|
||
|
def serve_next_queued_number(machine, priority_number \\ nil) do
|
||
|
GenServer.call(machine, {:serve_next_queued_number, priority_number})
|
||
|
end
|
||
|
|
||
|
@spec reset_state(pid()) :: :ok
|
||
|
def reset_state(machine) do
|
||
|
GenServer.cast(machine, :reset_state)
|
||
|
end
|
||
|
|
||
|
# Server callbacks
|
||
|
|
||
|
@impl GenServer
|
||
|
def init(options) do
|
||
|
with min <- Keyword.get(options, :min_number),
|
||
|
max <- Keyword.get(options, :max_number),
|
||
|
shutdown <- Keyword.get(options, :auto_shutdown_timeout, :infinity),
|
||
|
{:ok, state} <- State.new(min, max, shutdown) do
|
||
|
{:ok, state, shutdown}
|
||
|
else
|
||
|
_ -> {:stop, :invalid_configuration}
|
||
|
end
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_call(:report_state, _from, state) do
|
||
|
{:reply, state, state, state.auto_shutdown_timeout}
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_call(:queue_new_number, _from, state) do
|
||
|
case State.queue_new_number(state) do
|
||
|
{:ok, new_number, new_state} -> {:reply, {:ok, new_number}, new_state, new_state.auto_shutdown_timeout}
|
||
|
error -> {:reply, error, state, state.auto_shutdown_timeout}
|
||
|
end
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_call({:serve_next_queued_number, priority_number}, _from, state) do
|
||
|
case State.serve_next_queued_number(state, priority_number) do
|
||
|
{:ok, new_number, new_state} -> {:reply, {:ok, new_number}, new_state, new_state.auto_shutdown_timeout}
|
||
|
error -> {:reply, error, state, state.auto_shutdown_timeout}
|
||
|
end
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_call(_request, _from, state) do
|
||
|
{:reply, :unknown_command, state, state.auto_shutdown_timeout}
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_cast(
|
||
|
:reset_state,
|
||
|
%State{min_number: min_number, max_number: max_number, auto_shutdown_timeout: auto_shutdown_timeout}
|
||
|
) do
|
||
|
{:ok, new_state} = State.new(min_number, max_number, auto_shutdown_timeout)
|
||
|
{:noreply, new_state, new_state.auto_shutdown_timeout}
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_cast(_request, state) do
|
||
|
{:noreply, state, state.auto_shutdown_timeout}
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_info(:timeout, state) do
|
||
|
{:stop, :normal, state}
|
||
|
end
|
||
|
|
||
|
@impl GenServer
|
||
|
def handle_info(_request, state) do
|
||
|
{:noreply, state, state.auto_shutdown_timeout}
|
||
|
end
|
||
|
end
|