Redis.Connection (Redis v0.7.1)

Copy Markdown View Source

GenServer managing a single TCP/TLS connection to a Redis server.

Handles the socket lifecycle, RESP3 handshake, command sending/receiving, pipeline buffering, and automatic reconnection with exponential backoff.

Options

  • :host - Redis host (default: "127.0.0.1")
  • :port - Redis port (default: 6379)
  • :password - auth password (string or {mod, fun, args} MFA tuple)
  • :username - auth username (Redis 6+ ACL)
  • :database - database number to SELECT
  • :ssl - enable TLS (default: false)
  • :ssl_opts - SSL options list
  • :socket - Unix domain socket path (overrides host/port)
  • :name - GenServer name registration
  • :sync_connect - connect synchronously in init (default: true)
  • :backoff_initial - initial reconnect delay ms (default: 500)
  • :backoff_max - max reconnect delay ms (default: 30_000)
  • :protocol - :resp3 or :resp2 (default: :resp3)
  • :client_name - CLIENT SETNAME value
  • :timeout - command timeout ms (default: 5_000)
  • :credential_provider - {module, opts} implementing Redis.CredentialProvider for dynamic/rotating credentials (e.g., cloud IAM tokens). When set, :password and :username are ignored.
  • :exit_on_disconnection - exit instead of reconnecting (default: false)
  • :hibernate_after - idle ms before hibernation (default: nil)
  • :hooks - list of Redis.Hook modules for command middleware (default: [])

A Redis URI string may be passed as the first (sole) argument:

Connection.start_link("redis://:secret@localhost:6380/2")

Summary

Functions

Returns a child spec for supervision trees.

Sends a command without waiting for a reply. Uses CLIENT REPLY OFF/ON internally.

Sends multiple commands without waiting for replies.

Executes a WATCH-based optimistic locking transaction.

Functions

child_spec(init_arg)

Returns a child spec for supervision trees.

children = [
  {Redis.Connection, port: 6379, name: :redis}
]

noreply_command(conn, args, opts \\ [])

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

Sends a command without waiting for a reply. Uses CLIENT REPLY OFF/ON internally.

noreply_pipeline(conn, commands, opts \\ [])

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

Sends multiple commands without waiting for replies.

start_link()

start_link(uri)

@spec start_link(keyword() | String.t()) :: GenServer.on_start()

watch_transaction(conn, keys, fun, opts \\ [])

@spec watch_transaction(
  GenServer.server(),
  [String.t()],
  (GenServer.server() -> [[String.t()]] | {:abort, term()}),
  keyword()
) :: {:ok, [term()]} | {:error, term()}

Executes a WATCH-based optimistic locking transaction.

Watches the given keys, calls fun with the connection to read current values and compute commands, then executes those commands in a MULTI/EXEC block. If any watched key was modified by another client, EXEC returns nil and the function is retried (up to :max_retries times, default 3).

The function fun receives the connection and must return either:

  • a list of commands to execute in the transaction
  • {:abort, reason} to abort without executing

Returns {:ok, results} on success, {:error, :watch_conflict} if all retries are exhausted, or {:error, reason} on other failures.

Example

Redis.Connection.watch_transaction(conn, ["account:1", "account:2"], fn conn ->
  {:ok, bal1} = Redis.Connection.command(conn, ["GET", "account:1"])
  {:ok, bal2} = Redis.Connection.command(conn, ["GET", "account:2"])

  amount = 100
  new1 = String.to_integer(bal1) - amount
  new2 = String.to_integer(bal2) + amount

  [
    ["SET", "account:1", to_string(new1)],
    ["SET", "account:2", to_string(new2)]
  ]
end)