CrowdHailer / Ace

HTTP web server and client, supports http1 and http2
https://hex.pm/packages/ace
MIT License
305 stars 26 forks source link

drain connections #64

Closed CrowdHailer closed 6 years ago

CrowdHailer commented 7 years ago

New governor cannot be interupted to properly drain connections

  test "drain connection pool" do
    {:ok, server_supervisor} = Server.Supervisor.start_link({EchoServer, :explode})
    {:ok, socket} = :gen_tcp.listen(0, @socket_options)
    socket = {:tcp, socket}
    {:ok, port} = Connection.port(socket)

    {:ok, governor_supervisor} = Governor.Supervisor.start_link(server_supervisor, socket, 1)

    # Establish connection
    {:ok, client} = :gen_tcp.connect({127, 0, 0, 1}, port, [{:active, false}, :binary])
    :ok = :gen_tcp.send(client, "blob\n")
    assert {:ok, "ECHO: blob\n"} = :gen_tcp.recv(client, 0)

    # Drain connections
    :ok = Governor.Supervisor.drain(governor_supervisor)
    assert [] = Supervisor.which_children(governor_supervisor)
    assert [_1] = Supervisor.which_children(server_supervisor)

    # New connection not made
    {:ok, client2} = :gen_tcp.connect({127, 0, 0, 1}, port, [{:active, false}, :binary], 100)
    :ok = :gen_tcp.send(client2, "blob\n")
    assert {:error, :timeout} = :gen_tcp.recv(client2, 0, 100)

    # Establish connection still available
    :ok = :gen_tcp.send(client, "blob\n")
    assert {:ok, "ECHO: blob\n"} = :gen_tcp.recv(client, 0)
  end
  def drain(supervisor) do
    Supervisor.which_children(supervisor)
    |> Enum.map(fn({_i, pid, :worker, _}) ->
      ref = Process.monitor(pid)
      true = Process.exit(pid, :shutdown)
      ref
    end)
    |> Enum.map(fn(ref) ->
      receive do
        {:DOWN, ^ref, :process, _pid, _reason} ->
          :ok
      end
    end)
    :ok
  end
CrowdHailer commented 6 years ago

closed as I have no requirement for this. connections are drained by load balancer