Amarula.Protocol.Socket.ConnectionSupervisor (amarula v0.4.2)

View Source

Per-connection supervision tree. One ConnectionSupervisor owns everything for a single WhatsApp connection instance:

ConnectionSupervisor (:rest_for_one)
 Connection          (THE socket: ws + cipher + IQ + sends + consumer API;
                        also owns the retry-cache ETS table)
 SenderSupervisor    (DynamicSupervisor)  ConversationSender

Connection.make_socket/2 starts this supervisor and returns the Connection child pid — the consumer's handle, so the public API (connect/send_text/... on that pid) lands on Connection directly (no relay).

This tree has no Registry child of its own. The supervisor, its sibling roles, and each ConversationSender are named in the app-level Amarula.InstanceRegistry, keyed by the instance_id ref — so no atom is minted per connection and two connections can never collide. Siblings find each other by role via name/2 / whereis/2.

:rest_for_one (not :one_for_one) because senders block on Connection's IQ replies: if Connection restarts, the senders waiting on it must restart too. A sender crash, conversely, never restarts Connection.

Summary

Functions

Returns a specification to start this module under a supervisor.

The :via tuple addressing a sibling role in this instance's registry.

The app-level registry that names this instance's infrastructure. Constant (Amarula.InstanceRegistry) — keys carry the instance_id, so no per-instance Registry process and no minted atom.

Start a connection instance. opts may carry :parent_pid. Returns {:ok, sup_pid, connection_pid}connection_pid is the consumer handle.

Stop a whole connection tree by its instance_id (the supervisor + all children, freeing the profile registration). Returns :ok, or {:error, :not_found} if no such tree is running.

The :via tuple naming the tree supervisor, keyed by instance_id in the app-level Amarula.InstanceRegistry. No atom is minted per connection.

Resolve a sibling role to a pid, or :undefined.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

name(instance_id, role)

@spec name(reference(), atom()) :: {:via, Registry, {atom(), {reference(), atom()}}}

The :via tuple addressing a sibling role in this instance's registry.

registry_name(instance_id)

The app-level registry that names this instance's infrastructure. Constant (Amarula.InstanceRegistry) — keys carry the instance_id, so no per-instance Registry process and no minted atom.

start_instance(conn, opts \\ [])

@spec start_instance(
  Amarula.Conn.t(),
  keyword()
) :: {:ok, pid(), pid()} | {:error, term()}

Start a connection instance. opts may carry :parent_pid. Returns {:ok, sup_pid, connection_pid}connection_pid is the consumer handle.

The tree is started under the library-owned Amarula.ConnectionsSupervisor (a DynamicSupervisor), not linked to the calling consumer. A connection crash is therefore observable by the consumer through parent_pid events but never delivers an exit signal that would take the consumer down.

stop_instance(instance_id)

@spec stop_instance(reference()) :: :ok | {:error, :not_found}

Stop a whole connection tree by its instance_id (the supervisor + all children, freeing the profile registration). Returns :ok, or {:error, :not_found} if no such tree is running.

supervisor_name(instance_id)

@spec supervisor_name(reference()) :: {:via, Registry, term()}

The :via tuple naming the tree supervisor, keyed by instance_id in the app-level Amarula.InstanceRegistry. No atom is minted per connection.

whereis(instance_id, role)

@spec whereis(reference(), atom()) :: pid() | :undefined

Resolve a sibling role to a pid, or :undefined.