# `Redis.Cluster`
[🔗](https://github.com/joshrotenberg/redis_ex/blob/v0.7.1/lib/redis/cluster/cluster.ex#L1)

Redis Cluster client.

Maintains topology awareness, routes commands to the correct node based on
hash slot, and handles MOVED/ASK redirects transparently.

## Usage

    {:ok, cluster} = Redis.Cluster.start_link(
      nodes: [{"127.0.0.1", 7000}, {"127.0.0.1", 7001}],
      password: "secret"
    )

    {:ok, "OK"} = Redis.Cluster.command(cluster, ["SET", "mykey", "myvalue"])
    {:ok, "myvalue"} = Redis.Cluster.command(cluster, ["GET", "mykey"])

## Options

  * `:nodes` - list of seed nodes as `{host, port}` tuples or `"host:port"` strings
  * `:password` - Redis password (applied to all nodes)
  * `:name` - GenServer name registration
  * `:timeout` - command timeout ms (default: 5_000)
  * `:max_redirects` - max MOVED/ASK redirects before failing (default: 5)

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `command`

```elixir
@spec command(GenServer.server(), [String.t()], keyword()) ::
  {:ok, term()} | {:error, term()}
```

Sends a command, routed to the correct node by key hash slot.

# `info`

```elixir
@spec info(GenServer.server()) :: map()
```

Returns cluster info: nodes, slot coverage.

# `pipeline`

```elixir
@spec pipeline(GenServer.server(), [[String.t()]], keyword()) ::
  {:ok, [term()]} | {:error, term()}
```

Sends a pipeline of commands. If all commands target the same hash slot,
they are sent as a single pipeline. Otherwise, commands are automatically
split by slot, sent in parallel to the correct nodes, and results are
reassembled in the original command order.

# `refresh`

```elixir
@spec refresh(GenServer.server()) :: :ok | {:error, term()}
```

Forces a topology refresh.

# `start_link`

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

# `stop`

```elixir
@spec stop(GenServer.server()) :: :ok
```

# `transaction`

```elixir
@spec transaction(GenServer.server(), [[String.t()]], keyword()) ::
  {:ok, [term()]} | {:error, term()}
```

Executes a MULTI/EXEC transaction in cluster mode.

All commands must target the same hash slot. Returns `{:error, :cross_slot}`
if commands span multiple slots. Use hash tags (e.g. `{user}.name`) to
ensure related keys land in the same slot.

    Cluster.transaction(cluster, [
      ["SET", "{user:1}.name", "Alice"],
      ["SET", "{user:1}.email", "alice@example.com"]
    ])

# `watch_transaction`

```elixir
@spec watch_transaction(
  GenServer.server(),
  [String.t()],
  (GenServer.server() -&gt; [[String.t()]] | {:abort, term()}),
  keyword()
) :: {:ok, [term()]} | {:error, term()}
```

Executes a WATCH-based optimistic locking transaction in cluster mode.

All watched keys and all commands produced by the function must target
the same hash slot. Returns `{:error, :cross_slot}` if they don't.

    Cluster.watch_transaction(cluster, ["{acct:1}.balance"], fn conn ->
      {:ok, bal} = Redis.Connection.command(conn, ["GET", "{acct:1}.balance"])
      new_bal = String.to_integer(bal) + 100
      [["SET", "{acct:1}.balance", to_string(new_bal)]]
    end)

---

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