# `ZenWebsocket.ClientSupervisor`
[🔗](https://github.com/ZenHive/zen_websocket/blob/v0.4.2/lib/zen_websocket/client_supervisor.ex#L1)

Optional supervisor for WebSocket client connections.

Provides supervised client connections with automatic restart on failure.
Each client runs under its own supervisor for isolation.

## Restart Policy

Allows up to 10 restarts within 60 seconds. This prevents rapid restart loops
while allowing recovery from transient failures.

## Adding to Your Supervision Tree

    # In your application supervisor
    children = [
      # Start the ClientSupervisor
      ZenWebsocket.ClientSupervisor,
      # Your other children...
    ]
    
    Supervisor.start_link(children, strategy: :one_for_one)

## Usage

    # After supervisor is started, create supervised connections
    {:ok, client} = ClientSupervisor.start_client("wss://example.com", 
      retry_count: 5,
      heartbeat_config: %{type: :deribit, interval: 30_000}
    )
    
    # The client will be automatically restarted on crashes
    # with exponential backoff between restarts

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `send_balanced` | 2 | Send a message using health-based load balancing with failover. | `message: value`, `opts: value` |
| `stop_client` | 1 | Gracefully stop a supervised client. | `pid: value` |
| `list_clients` | 0 | List all supervised client connections. | - |
| `start_client` | 2 | Start a supervised WebSocket client with automatic restart. | `url_or_config: value`, `opts: value` |

# `discovery_fun`

```elixir
@type discovery_fun() :: (-&gt; [pid()])
```

Function that returns a list of client PIDs for load balancing

# `lifecycle_callback`

```elixir
@type lifecycle_callback() :: (pid() -&gt; any())
```

Callback invoked on client lifecycle events

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `list_clients`

```elixir
@spec list_clients() :: [pid()]
```

Lists all supervised client connections.

# `send_balanced`

```elixir
@spec send_balanced(
  binary(),
  keyword()
) :: :ok | {:ok, map()} | {:error, term()}
```

Sends a message using health-based load balancing.

Selects the healthiest connection from the pool and sends the message.
On failure, records the error and attempts failover to the next healthiest
connection.

## Options

- `:max_attempts` - Maximum failover attempts (default: 3)
- `:client_discovery` - Function returning list of PIDs (default: `list_clients/0`)

## Examples

    :ok = ClientSupervisor.send_balanced(message)
    {:ok, response} = ClientSupervisor.send_balanced(rpc_message)
    {:error, :no_connections} = ClientSupervisor.send_balanced(message)

    # With custom discovery (e.g., distributed with :pg)
    :ok = ClientSupervisor.send_balanced(message,
      client_discovery: fn -> :pg.get_members(:ws_pool) end
    )

# `start_client`

```elixir
@spec start_client(
  String.t() | ZenWebsocket.Config.t(),
  keyword()
) :: {:ok, ZenWebsocket.Client.t()} | {:error, term()}
```

Starts a supervised WebSocket client.

The client will be automatically restarted on failure according to the
supervisor's restart strategy.

## Lifecycle Callbacks

- `:on_connect` - Called with the client PID after successful connection.
  Use to register the client with external registries (`:pg`, `Horde`, etc.).
- `:on_disconnect` - Called with the client PID when the client terminates.
  Use to unregister from external registries.

## Examples

    # Basic usage
    {:ok, client} = ClientSupervisor.start_client("wss://example.com")

    # With lifecycle callbacks for distributed registry
    {:ok, client} = ClientSupervisor.start_client("wss://example.com",
      on_connect: fn pid -> :pg.join(:ws_pool, pid) end,
      on_disconnect: fn pid -> :pg.leave(:ws_pool, pid) end
    )

# `start_link`

```elixir
@spec start_link(term()) :: Supervisor.on_start()
```

Starts the client supervisor.

# `stop_client`

```elixir
@spec stop_client(pid()) :: :ok | {:error, :not_found}
```

Gracefully stops a supervised client.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
