# `AshScylla.Connection`
[🔗](https://github.com/ohhi-vn/ash_scylla/blob/main/lib/ash_scylla/connection.ex#L15)

GenServer wrapper for Xandra connections.

Provides a process-based connection to ScyllaDB/Cassandra via Xandra,
supporting both single-node and cluster connection modes.

## Usage

    {:ok, pid} = AshScylla.Connection.start_link(nodes: ["127.0.0.1:9042"])
    AshScylla.Connection.query(pid, "SELECT * FROM system.local", [])
    AshScylla.Connection.stop(pid)

## Options

- `:name` — Register the connection under a name (for `get_conn/1`)
- `:nodes` — List of ScyllaDB nodes
- `:keyspace` — Default keyspace for the connection
- `:connect_timeout` — TCP connection timeout in ms (default: 5000)

## Cluster Mode

When multiple nodes are provided, Xandra.Cluster is used for
automatic node discovery and load balancing.

### Single-node connection

    children = [
      {AshScylla.Connection, name: MyApp.Scylla, nodes: ["127.0.0.1:9042"], keyspace: "my_app"}
    ]

    {:ok, conn} = AshScylla.Connection.start_link(nodes: ["127.0.0.1:9042"], keyspace: "my_app")

### Multi-node cluster connection

All nodes must use the same port:

    children = [
      {AshScylla.Connection,
        name: MyApp.Scylla,
        nodes: ["scylla-1:9042", "scylla-2:9042", "scylla-3:9042"],
        keyspace: "my_app",
        pool_size: 10}
    ]

### Cluster Mode Details

When multiple nodes are provided, `AshScylla.Connection` uses `Xandra.Cluster`
for load balancing and fault tolerance.

**Important:** Xandra.Cluster requires all nodes to share the same port.
It uses a single `autodiscovered_nodes_port` for all discovered peers
(Scylla/Cassandra `system.peers` does not advertise ports).

If nodes have different ports, `AshScylla.Connection` falls back to a
single-node connection to the first node and logs a warning.

# `t`

```elixir
@type t() :: %AshScylla.Connection{
  cluster?: boolean(),
  conn: pid(),
  keyspace: String.t() | nil,
  keyspace_used: boolean(),
  nodes: [String.t()]
}
```

# `child_spec`

```elixir
@spec child_spec(keyword()) :: Supervisor.child_spec()
```

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `ensure_keyspace!`

Ensures the keyspace is selected. Retries USE if not yet applied.

# `get_conn`

```elixir
@spec get_conn(module() | atom()) :: t() | nil
```

Returns the connection struct by name (local or global).

# `prepare`

```elixir
@spec prepare(t() | module(), String.t(), keyword()) ::
  {:ok, Xandra.Prepared.t()} | {:error, term()}
```

Prepares a CQL statement.

# `prepare!`

```elixir
@spec prepare!(t() | module(), String.t(), keyword()) ::
  Xandra.Prepared.t() | no_return()
```

Prepares a CQL statement, raising on error.

# `query`

```elixir
@spec query(t() | module(), String.t(), list(), keyword()) ::
  {:ok, term()} | {:error, term()}
```

Executes a simple or prepared query.

Automatically types simple query values for Xandra 0.19.x compatibility.
Xandra requires typed `{type_string, value}` tuples for simple query parameters,
so we wrap raw Elixir values in their appropriate CQL type annotations.

# `query!`

```elixir
@spec query!(t() | module(), String.t(), list(), keyword()) :: term() | no_return()
```

Executes a simple or prepared query, raising on error.

# `reconnect_keyspace`

```elixir
@spec reconnect_keyspace(atom()) :: {:ok, :set} | {:error, term()}
```

Reconnects to the keyspace. Useful after the keyspace has been created.
Returns `{:ok, :set}` or `{:error, reason}`.

# `release_session`

```elixir
@spec release_session(atom()) :: :ok | {:error, term()}
```

Releases the keyspace session binding for a named connection.

Switches the connection's default keyspace to `system` so that the next
DROP KEYSPACE is not blocked by an active `USE <keyspace>` session on this
connection. ScyllaDB defers/blocks the drop while another connection holds
a session on that keyspace. Returns `:ok` if there was no active session
or the release succeeded, `{:error, reason}` otherwise.

# `set_keyspace`

```elixir
@spec set_keyspace(atom(), String.t()) :: {:ok, :set} | {:error, term()}
```

Sets the keyspace to use. Useful when the keyspace is created after connection start.
Returns `{:ok, :set}` or `{:error, reason}`.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

# `stop`

```elixir
@spec stop(t() | module()) :: :ok
```

Stops the connection.

# `typed_params`

```elixir
@spec typed_params(list()) :: list()
```

Converts raw Elixir values to typed Xandra params.

Xandra 0.19.x requires simple query values to be `{type_string, value}` tuples.
This function infers the CQL type from the Elixir type.

---

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