From 9bae951c555f9c25876968fa98853253b7007a0f Mon Sep 17 00:00:00 2001 From: kballou Date: Fri, 24 Nov 2017 10:16:06 -0700 Subject: Level up the Echo Server This should enable the upgrade process to retain connections - Replace our simple task supervisor with a custom `simple_one_for_one` supervisor - Upgrade the echo server to use a `GenServer` behaviour --- lib/octonetcat/accepter.ex | 6 +----- lib/octonetcat/server_supervisor.ex | 23 +++++++++++++++++++++++ lib/octonetcat/servers/echo.ex | 28 ++++++++++++++++------------ lib/octonetcat/supervisor.ex | 2 +- mix.exs | 2 +- 5 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 lib/octonetcat/server_supervisor.ex diff --git a/lib/octonetcat/accepter.ex b/lib/octonetcat/accepter.ex index a398676..9a570c1 100644 --- a/lib/octonetcat/accepter.ex +++ b/lib/octonetcat/accepter.ex @@ -18,11 +18,7 @@ defmodule Octonetcat.Accepter do {:ok, client} = :gen_tcp.accept(socket) Logger.info("Accepted connection") Logger.info("Passing to Echo Server") - {:ok, pid} = Task.Supervisor.start_child( - Octonetcat.TaskSupervisor, - Octonetcat.Echo, - :serve, - [client]) + {:ok, pid} = Octonetcat.ServerSupervisor.start_server(client) :ok = :gen_tcp.controlling_process(client, pid) loop_accepter(socket) end diff --git a/lib/octonetcat/server_supervisor.ex b/lib/octonetcat/server_supervisor.ex new file mode 100644 index 0000000..7aa8e37 --- /dev/null +++ b/lib/octonetcat/server_supervisor.ex @@ -0,0 +1,23 @@ +defmodule Octonetcat.ServerSupervisor do + @moduledoc """ + Simple One-for-One Supervisor for Socket servers + """ + + use Supervisor + + def start_link do + Supervisor.start_link(__MODULE__, :ok, name: __MODULE__) + end + + def init(:ok) do + children = [ + worker(Octonetcat.Echo, [], restart: :temporary) + ] + + supervise(children, strategy: :simple_one_for_one) + end + + def start_server(socket) do + Supervisor.start_child(__MODULE__, [socket]) + end +end diff --git a/lib/octonetcat/servers/echo.ex b/lib/octonetcat/servers/echo.ex index e416d9d..8ad6aff 100644 --- a/lib/octonetcat/servers/echo.ex +++ b/lib/octonetcat/servers/echo.ex @@ -6,23 +6,27 @@ defmodule Octonetcat.Echo do dies on failure or disconnect. """ + use GenServer require Logger - def serve(socket) do - socket - |> read_line() - |> write_line!(socket) + def start_link(socket) do + GenServer.start_link(__MODULE__, socket) + end - serve(socket) + def init(socket) do + :ok = :inet.setopts(socket, active: true) + {:ok, %{socket: socket}} + end + + def handle_info({:tcp, _, msg}, state = %{socket: socket}) do + msg + |> write_line!(socket) + {:noreply, state} end - def read_line(socket) do - case :gen_tcp.recv(socket, 0) do - {:ok, line} -> line - {:error, reason} -> - Logger.error(reason) - Process.exit(self(), :normal) - end + def handle_info({:tcp_closed, _}, _state) do + Logger.info("#{__MODULE__}: Connection closing...") + {:stop, :normal, %{}} end def write_line!(line, socket) do diff --git a/lib/octonetcat/supervisor.ex b/lib/octonetcat/supervisor.ex index 50a5f66..64bc27c 100644 --- a/lib/octonetcat/supervisor.ex +++ b/lib/octonetcat/supervisor.ex @@ -11,7 +11,7 @@ defmodule Octonetcat.Supervisor do def init(_) do children = [ - supervisor(Task.Supervisor, [[name: Octonetcat.TaskSupervisor]]), + supervisor(Octonetcat.ServerSupervisor, []), worker(Task, [Octonetcat.Accepter, :accept, []]) ] diff --git a/mix.exs b/mix.exs index e96830b..954f1ec 100644 --- a/mix.exs +++ b/mix.exs @@ -6,7 +6,7 @@ defmodule Octonetcat.Mixfile do app: :octonetcat, description: "Demo Echo Server Application", package: package(), - version: "0.2.1", + version: "0.3.0", elixir: "~> 1.5", start_permanent: Mix.env == :prod, docs: docs(), -- cgit v1.2.1