jonnifyelixir
F6 / F6.01 / endpoint

F6.01 · part 2 of 3

The endpoint, supervised

The endpoint wears two hats, and seeing both is what connects Phoenix to everything F5 built. As a plug, PortalWeb.Endpoint is the outermost layer of the request lifecycle — the fixed stack of static files, parsers, and session that every request passes through before the router. As a process, it is a supervised child of the OTP tree: when the application boots, the endpoint starts listening, and if it crashes its supervisor restarts it, exactly like the engine and the store from F5. That second hat is the whole structural change F6 makes — one more child added to the tree the F5.09 lab assembled, sitting beside the engine rather than wrapping it.

See the endpoint’s two roles, where it sits in the supervision tree, and the code for both — the plug stack and the one-line addition to the tree.

Two roles, one module

The same module is configured two ways. Its plug declarations make it the head of the request pipeline; its place in Application.start/2 makes it a supervised process that owns the listening socket. Select a role to see what it covers.

The endpoint’s roles · select one

PLUG STACK static · request id · parsers · session · router the lifecycle head SOCKET socket "/live", Phoenix.LiveView.Socket LiveView · F6.06 TREE CHILD supervised beside Portal.Engine in F5’s tree OTP

role: Plug stack

is: static files, parsers, session, router

One module, two contracts: a plug for the request path and a child spec for the supervisor. The first makes it part of the lifecycle; the second makes it part of OTP — the bridge between HTTP and the BEAM.

Where it sits in the tree

The endpoint is added to the supervision tree the F5.09 lab assembled, under the same :one_for_one strategy. The store and the engine entries do not move; the endpoint is one more child, started alongside them. A request the endpoint accepts is handled by calling the engine that is its sibling, never by reaching around the supervisor.

Portal.Supervisor · one new child

PORTAL.SUPERVISOR :one_for_one EVENTSTORE F5 · store ENGINE F5 · GenServer PORTALWEB.ENDPOINT F6 · web (new) the endpoint owns the listening socket; the engine and store are unchanged siblings

A web server that is a supervised process is a BEAM idea, not a Phoenix one. The endpoint inherits the same fault tolerance as the engine: if it falls over, the supervisor brings it back, and the engine beside it never noticed.

The endpoint in code

The endpoint module is mostly an ordered list of plugs ending in the router; both roles are visible in it. Adding it to the tree is a single line in Application.start/2 — the same list the F5.09 lab built, with one entry appended.

# the endpoint: the head of the request pipeline (a plug) ...
defmodule PortalWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :portal

  socket "/live", Phoenix.LiveView.Socket     # LiveView entry (F6.06)

  plug Plug.Static, at: "/", from: :portal
  plug Plug.RequestId
  plug Plug.Parsers, parsers: [:urlencoded, :multipart, :json], json_decoder: Jason
  plug Plug.Session, store: :cookie, key: "_portal_key"
  plug PortalWeb.Router                       # the last plug: match → controller
end

# ... and a supervised child of the F5.09 tree (one line added)
children = [
  Portal.EventStore.adapter(),   # F5 — unchanged
  {Portal.Engine, []},            # F5 — unchanged
  PortalWeb.Endpoint             # F6 — supervised alongside
]
Supervisor.start_link(children, strategy: :one_for_one, name: Portal.Supervisor)

a plug

The outermost layer of the lifecycle — the stack every request passes through.

a process

A supervised child beside the engine — the one structural change F6 makes.

Next: controllers, views & the facade seam — once a request reaches the router, where does your code call the engine?

References

Primary sources for this lesson, and where it connects in the course.