TermUI.ComponentSupervisor (TermUI v0.2.0)

View Source

Dynamic supervisor for managing component processes.

Components are spawned as child processes under this supervisor, providing fault isolation and automatic cleanup. Each component runs as a GenServer managed by TermUI.ComponentServer.

Usage

# Start a component under the supervisor
{:ok, pid} = ComponentSupervisor.start_component(MyComponent, %{text: "Hello"})

# Stop a component
:ok = ComponentSupervisor.stop_component(pid)

# Stop with cascade (stops all children)
:ok = ComponentSupervisor.stop_component(pid, cascade: true)

Supervision Strategy

Uses :one_for_one strategy - each component is independent. Default restart is :transient - restart only on crash, not normal exit.

Restart Strategies

  • :transient (default) - Restart only on abnormal termination
  • :permanent - Always restart on termination
  • :temporary - Never restart

Shutdown Options

  • :shutdown - Timeout in ms (default 5000) or :brutal_kill
  • :recovery - Recovery mode: :reset, :last_props, :last_state

Summary

Functions

Returns a specification to start this module under a supervisor.

Returns the count of running components.

Returns a text visualization of the component tree.

Returns detailed information about a component.

Returns the component tree structure.

Starts a component under the supervisor.

Starts the component supervisor.

Stops a component gracefully.

Returns all component pids.

Functions

child_spec(arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

count_children()

@spec count_children() :: non_neg_integer()

Returns the count of running components.

format_tree()

@spec format_tree() :: String.t()

Returns a text visualization of the component tree.

Useful for debugging and logging.

Examples

IO.puts(ComponentSupervisor.format_tree())
# └─ :root (MyApp.Root) #PID<0.123.0>
#    ├─ :sidebar (MyApp.Sidebar) #PID<0.124.0>
#    └─ :content (MyApp.Content) #PID<0.125.0>

get_component_info(id)

@spec get_component_info(term()) :: {:ok, map()} | {:error, :not_found}

Returns detailed information about a component.

Parameters

  • id - Component identifier

Returns

  • {:ok, info} - Component information map
  • {:error, :not_found} - Component not found

The info map contains:

  • :id - Component identifier
  • :pid - Process identifier
  • :module - Component module
  • :lifecycle - Current lifecycle stage
  • :restart_count - Number of times restarted
  • :uptime_ms - Milliseconds since process started
  • :state - Current component state
  • :props - Current props

Examples

{:ok, info} = ComponentSupervisor.get_component_info(:my_button)
info.uptime_ms
# => 12345

get_tree()

@spec get_tree() :: [map()]

Returns the component tree structure.

Builds a hierarchical view of all components based on their parent-child relationships in the registry.

Returns

A list of tree nodes, where each node contains:

  • :id - Component identifier
  • :pid - Process identifier
  • :module - Component module
  • :children - List of child nodes

Examples

tree = ComponentSupervisor.get_tree()
# [
#   %{id: :root, pid: #PID<0.123.0>, module: MyApp.Root, children: [
#     %{id: :child1, pid: #PID<0.124.0>, module: MyApp.Child, children: []}
#   ]}
# ]

start_component(module, props, opts \\ [])

@spec start_component(module(), map(), keyword()) ::
  DynamicSupervisor.on_start_child()

Starts a component under the supervisor.

Parameters

  • module - The component module implementing a behaviour
  • props - Initial properties for the component
  • opts - Options including :id for component identification

Options

  • :id - Component identifier for registry lookup
  • :name - Process name registration
  • :timeout - Init timeout in milliseconds (default 5000)
  • :restart - Restart strategy: :transient, :permanent, :temporary (default :transient)
  • :shutdown - Shutdown timeout in ms or :brutal_kill (default 5000)
  • :recovery - Recovery mode: :reset, :last_props, :last_state (default :last_state)

Returns

  • {:ok, pid} - Component started successfully
  • {:error, reason} - Failed to start

Examples

{:ok, pid} = ComponentSupervisor.start_component(Label, %{text: "Hello"})

{:ok, pid} = ComponentSupervisor.start_component(
  Button,
  %{label: "Click"},
  id: :submit_button
)

start_link(opts \\ [])

@spec start_link(keyword()) :: Supervisor.on_start()

Starts the component supervisor.

Called by the application supervisor during startup.

stop_component(pid_or_id, opts \\ [])

@spec stop_component(
  pid() | term(),
  keyword()
) :: :ok | {:error, :not_found}

Stops a component gracefully.

Triggers the unmount lifecycle before termination.

Parameters

  • pid_or_id - The component process pid or id
  • opts - Options
    • :cascade - Also stop all child components (default: false)

Returns

  • :ok - Component stopped successfully
  • {:error, :not_found} - Component not found

which_children()

@spec which_children() :: [pid()]

Returns all component pids.