GamendWeb.HostSupervision (gamend_web v1.0.1215)

Copy Markdown View Source

The canonical supervision tree for a Gamend host application.

A host app owns its own Application.start/2, so historically it also owned a hand-written children list. That list is not host-specific — it is core's, and every core feature that adds a process needs a line in every host's copy. Nothing enforces that, and nothing fails loudly when it is missed: a missing child means enqueues target a process that was never started, so the feature silently no-ops while its config still reads "on".

That is not hypothetical. Before this module existed, one host had drifted by six children (Cache.Stats, Cache.Sync, IpBanSync, Retention, Tournaments.Ticker, Matchmaking.Worker), an unbounded task supervisor, and the lobby-snapshots writer — the last of which cost a full debugging session to find, because every other signal said capture was working.

So the list lives here, next to the features that populate it, and hosts call children/1. Host-specific processes go in :extra rather than into a fork of the list.

Usage

def start(_type, _args) do
  GamendWeb.HostSupervision.init_runtime()

  Supervisor.start_link(
    GamendWeb.HostSupervision.children(extra: [MyHost.Thing]),
    strategy: :one_for_one,
    name: MyHost.Supervisor
  )
end

Summary

Functions

Core's children, in start order.

Set up the ETS tables and OS services children assume already exist.

Functions

children(opts \\ [])

@spec children(keyword()) :: [Supervisor.child_spec() | {module(), term()} | module()]

Core's children, in start order.

Options:

  • :plugins — start Gamend.Hooks.PluginManager (default true). Hosts that ship no plugins, and test configs that load them separately, pass false.
  • :extra — host-specific children, appended after core's. Anything here is genuinely host-owned; if it is a core feature it belongs in this list instead, so every host gets it.

Order matters and is deliberate: Repo and Cache before anything that reads them, PluginManager before Endpoint so hooks resolve on the first request, and the periodic workers last so a slow sweep never delays boot.

init_runtime()

@spec init_runtime() :: :ok

Set up the ETS tables and OS services children assume already exist.

Must run before children/1 is supervised: the Schedule tick reads the registry Gamend.Schedule.start_link/0 creates, and the ban/geo plugs read theirs on the first request. Safe to call more than once.