TheEnd

This library provides a graceful shutdown support for your Phoenix, or plain Plug application.

Original idea is

https://gist.github.com/aaronjensen/33cc2aeb74746cac3bcb40dcefdd9c09

Many of the logic in this library is borrowed from here. I added a little bit componentization

Now, with this library, you can support graceful shutdown for your application built with

And you also can use only AcceptanceStopper, without waiting pending requests to finish. This is for WebSocket application.

Installation

If available in Hex, the package can be installed by adding the_end to your list of dependencies in mix.exs:

def deps do
  [
    {:the_end, "~> 1.1.0"}
  ]
end

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/the_end.

Usage

Phoenix Endpoint

  children = [

    {MyApp.Endpoint, []},

    # ... other supervisors/workers

    # you should set this supervisor at last
    {TheEnd.Of.Phoenix, [timeout: 10_000, endpoint: MyApp.Endpoint]}
  ]
  Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)

If your Phoenix version is 1.2 or older, use TheEnd.Of.LegacyPhoenix instead of TheEnd.Of.Phoenix.

Plug

Your need a Plug wrapper supervisor

defmodule MyApp.HTTPSupervisor do

  use Supervisor

  def start_link() do
    Supervisor.start_link(__MODULE__, nil, name: __MODULE__)
  end

  def init(_args) do
      [Plug.Adapters.Cowboy.child_spec(:http,
        MyApp.Router, [], [port: 3000])]
    |> Supervisor.init(strategy: :one_for_one)
  end

end
  children = [

    MyApp.HTTPSupervisor,

    # ... other supervisors/workers

    # you should set this supervisor at last
    {TheEnd.Of.Plug, [timeout: 10_000, endpoint: MyApp.HTTPSupervisor]}
  ]

  Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)

Or else if you don't need to wait for requests to finish. (For instance, WebSocket application)

  children = [

    {MyApp.HTTPSupervisor[]},

    # ... other supervisors/workers

    # you should set this worker at last
    {TheEnd.AcceptanceStopper,
     [gatherer: TheEnd.ListenerGatherer.Plug, endpoint: MyApp.HTTPSupervisor]}
  ]

  Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)

You can choose gatherer option for your situation