From 3bcdc01d8de970905bf923e5cddc7a567d12de0e Mon Sep 17 00:00:00 2001 From: kballou Date: Mon, 31 Oct 2016 03:23:48 -0600 Subject: Level up our echo server This should enable upgrade process to retain connections * Replace our simple task supervisor with a custom `simple_one_for_one` supervisor * Upgrade our echo server to use a `GenServer` behaviour --- lib/octochat/acceptor.ex | 6 +----- lib/octochat/server_supervisor.ex | 24 ++++++++++++++++++++++++ lib/octochat/servers/echo.ex | 28 ++++++++++++++++------------ lib/octochat/supervisor.ex | 2 +- mix.exs | 2 +- 5 files changed, 43 insertions(+), 19 deletions(-) create mode 100644 lib/octochat/server_supervisor.ex diff --git a/lib/octochat/acceptor.ex b/lib/octochat/acceptor.ex index 5730ee4..28d14be 100644 --- a/lib/octochat/acceptor.ex +++ b/lib/octochat/acceptor.ex @@ -14,11 +14,7 @@ defmodule Octochat.Acceptor do defp loop_acceptor(socket) do {:ok, client} = :gen_tcp.accept(socket) - {:ok, pid} = Task.Supervisor.start_child( - Octochat.TaskSupervisor, - Octochat.Echo, - :serve, - [client]) + {:ok, pid} = Octochat.ServerSupervisor.start_server(client) :ok = :gen_tcp.controlling_process(client, pid) loop_acceptor(socket) end diff --git a/lib/octochat/server_supervisor.ex b/lib/octochat/server_supervisor.ex new file mode 100644 index 0000000..d412ca5 --- /dev/null +++ b/lib/octochat/server_supervisor.ex @@ -0,0 +1,24 @@ +defmodule Octochat.ServerSupervisor do + @moduledoc """ + Simple One-for-One Supervisor for socket connections + """ + + use Supervisor + + def start_link() do + Supervisor.start_link(__MODULE__, :ok, name: __MODULE__) + end + + def init(:ok) do + children = [ + worker(Octochat.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/octochat/servers/echo.ex b/lib/octochat/servers/echo.ex index da04876..bea9864 100644 --- a/lib/octochat/servers/echo.ex +++ b/lib/octochat/servers/echo.ex @@ -2,23 +2,27 @@ defmodule Octochat.Echo do @moduledoc """ Octochat Echo server """ + 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 - defp 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 defp write_line!(line, socket) do diff --git a/lib/octochat/supervisor.ex b/lib/octochat/supervisor.ex index d551628..9882942 100644 --- a/lib/octochat/supervisor.ex +++ b/lib/octochat/supervisor.ex @@ -11,7 +11,7 @@ defmodule Octochat.Supervisor do def init(_) do children = [ - supervisor(Task.Supervisor, [[name: Octochat.TaskSupervisor]]), + supervisor(Octochat.ServerSupervisor, []), worker(Task, [Octochat.Acceptor, :accept, []]) ] diff --git a/mix.exs b/mix.exs index b504c69..a5bd07f 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule Octochat.Mixfile do [app: :octochat, description: "Demo Application for How Swapping Code", package: package(), - version: "0.2.1", + version: "0.3.0", elixir: "~> 1.3", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, -- cgit v1.2.1