# lib/forum/application.ex defmodule Forum.Application do use Application @impl true def start(_type, _args) do db_config = Application.fetch_env!(:forum, Forum.DB) server_config = Application.fetch_env!(:forum, :server) children = [ {Postgrex, [name: Forum.DB] ++ db_config}, # Unique process names for forms, networks, public sites, and HTTP servers. {Registry, keys: :unique, name: Forum.ProcessRegistry}, # WebSocket clients subscribe here for live forms.html updates. {Registry, keys: :duplicate, name: Forum.FormsSubscriberRegistry}, Forum.LogStore, Forum.Networks, Forum.PublicSiteSupervisor, # Parses forms.html and supervises one QuickBEAM runtime per # child element. Also serves Forum.Forms.html/0. Forum.Forms, # Re-parses forms.html whenever the file changes on disk. Forum.Forms.Watcher, # Main HTTP + WebSocket server. http_server_child(:main, Forum.Router, server_config[:port]) ] ++ network_site_servers(server_config) with {:ok, sup} <- Supervisor.start_link(children, strategy: :one_for_one, name: Forum.Supervisor) do # DynamicSupervisor can't start children from its own init/1, so # we kick off the initial parse + spawn here. Forum.Forms.reload() Forum.Networks.start_networks() Forum.PublicSiteSupervisor.start_networks() {:ok, sup} end end defp network_site_servers(server_config) do base_port = Keyword.get(server_config, :network_port_base, 4001) Forum.Networks.network_slugs() |> Enum.with_index() |> Enum.map(fn {network, index} -> http_server_child( {:network, network}, {Forum.PublicSiteRouter, network: network}, base_port + index ) end) end defp http_server_child(key, plug, port) do Supervisor.child_spec( {Bandit, plug: plug, port: port, thousand_island_options: [ supervisor_options: [ name: {:via, Registry, {Forum.ProcessRegistry, {:http_server, key}}} ] ]}, id: {:http_server, key, port} ) end end