From b20dbe988c1bc79f486fdc081c2c3209be3f0564 Mon Sep 17 00:00:00 2001 From: Jean-Francois Cloutier Date: Mon, 28 Mar 2022 13:38:28 -0400 Subject: [PATCH] Disable Connection.Controller before shutdown Stopping it had its supervisor restart it just before actual shutdown --- lib/tortoise311/connection/controller.ex | 41 +++++++++++++++----- test/tortoise/connection/controller_test.exs | 4 +- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/tortoise311/connection/controller.ex b/lib/tortoise311/connection/controller.ex index a691e47..dda0296 100644 --- a/lib/tortoise311/connection/controller.ex +++ b/lib/tortoise311/connection/controller.ex @@ -50,8 +50,10 @@ defmodule Tortoise311.Connection.Controller do Tortoise311.Registry.via_name(__MODULE__, client_id) end + # This is sent just before the Controller's supervisor is shutdown. + # All we want to do here is disable the controller until it is terminated by its supervisor shutting down. def stop(client_id) do - GenServer.stop(via_name(client_id)) + GenServer.cast(via_name(client_id), :stop) end def info(client_id) do @@ -123,6 +125,11 @@ defmodule Tortoise311.Connection.Controller do end @impl GenServer + + def handle_cast(_, %State{status: :stopped} = state), do: {:noreply, state} + + def handle_cast(:stop, state), do: {:noreply, %State{state | status: :stopped}} + def handle_cast({:incoming, <>}, state) do package |> Package.decode() @@ -152,9 +159,13 @@ defmodule Tortoise311.Connection.Controller do {:result, {Package.Subscribe, subacks}}, %State{handler: handler} = state ) do - case Handler.execute(handler, {:subscribe, subacks}) do - {:ok, updated_handler} -> - {:noreply, %State{state | handler: updated_handler}} + if state.status != :stopped do + case Handler.execute(handler, {:subscribe, subacks}) do + {:ok, updated_handler} -> + {:noreply, %State{state | handler: updated_handler}} + end + else + {:noreply, state} end end @@ -162,9 +173,13 @@ defmodule Tortoise311.Connection.Controller do {:result, {Package.Unsubscribe, unsubacks}}, %State{handler: handler} = state ) do - case Handler.execute(handler, {:unsubscribe, unsubacks}) do - {:ok, updated_handler} -> - {:noreply, %State{state | handler: updated_handler}} + if state.status != :stopped do + case Handler.execute(handler, {:unsubscribe, unsubacks}) do + {:ok, updated_handler} -> + {:noreply, %State{state | handler: updated_handler}} + end + else + {:noreply, state} end end @@ -175,13 +190,19 @@ defmodule Tortoise311.Connection.Controller do {:onward, %Package.Publish{qos: 2, dup: false} = publish}, %State{handler: handler} = state ) do - case Handler.execute(handler, {:publish, publish}) do - {:ok, updated_handler} -> - {:noreply, %State{state | handler: updated_handler}} + if state.status != :stopped do + case Handler.execute(handler, {:publish, publish}) do + {:ok, updated_handler} -> + {:noreply, %State{state | handler: updated_handler}} + end + else + {:noreply, state} end end @impl GenServer + def handle_info(_, %State{status: :stopped} = state), do: {:noreply, state} + def handle_info({:next_action, {:subscribe, topic, opts} = action}, state) do {qos, opts} = Keyword.pop_first(opts, :qos, 0) diff --git a/test/tortoise/connection/controller_test.exs b/test/tortoise/connection/controller_test.exs index dc09749..68df2b6 100644 --- a/test/tortoise/connection/controller_test.exs +++ b/test/tortoise/connection/controller_test.exs @@ -123,8 +123,8 @@ defmodule Tortoise311.Connection.ControllerTest do assert {:ok, pid} = Controller.start_link(opts) assert Process.alive?(pid) assert :ok = Controller.stop(context.client_id) - refute Process.alive?(pid) - assert_receive {:terminating, :normal} + state = Controller.info(context.client_id) + assert state.status == :stopped end describe "Connection callback" do