diff --git a/src/content/docs/concepts/client-features/client-side-caching.mdx b/src/content/docs/concepts/client-features/client-side-caching.mdx
index ba8f5d27..7862473e 100644
--- a/src/content/docs/concepts/client-features/client-side-caching.mdx
+++ b/src/content/docs/concepts/client-features/client-side-caching.mdx
@@ -535,11 +535,10 @@ Multiple clients can share the same cache instance by passing the same `ClientSi
## Server-Assisted Invalidation
Server-assisted invalidation can be enabled in the client side configuration by setting server assisted to true.
-You do not need to call [`CLIENT TRACKING`](https://valkey.io/commands/client-tracking/) yourself; GLIDE issues `CLIENT TRACKING ON BCAST` on your behalf during connection setup.
+You do not need to call [`CLIENT TRACKING`](https://valkey.io/commands/client-tracking/) yourself; GLIDE issues `CLIENT TRACKING ON BCAST` on your behalf during connection setup.
Once enabled, the client receives push invalidation messages from the server whenever a cached key is modified, eliminating the staleness window inherent in TTL-only mode — the server notifies the client immediately when data changes, and the client removes the stale entry from its local cache.
-
### Enabling server-assisted mode
diff --git a/src/content/docs/how-to/client-initialization.mdx b/src/content/docs/how-to/client-initialization.mdx
index b4c0d927..b22a2e96 100644
--- a/src/content/docs/how-to/client-initialization.mdx
+++ b/src/content/docs/how-to/client-initialization.mdx
@@ -111,6 +111,17 @@ The `NodeAddress` type represents the host and port of a cluster node. The host
await using var client = await GlideClusterClient.CreateClient(config);
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true
+ )
+ ```
+
### Request Routing
@@ -143,6 +154,10 @@ For more details on the routing of specific commands:
Please refer to [the documentation within the code](https://github.com/valkey-io/valkey-glide-csharp/blob/main/sources/Valkey.Glide/Route.cs) for routing configuration.
+
+
+ Please refer to [the documentation within the code](https://github.com/valkey-io/valkey-glide-ruby/blob/main/lib/valkey/route.rb) for routing configuration.
+
### Response Aggregation
@@ -175,6 +190,10 @@ To learn more about response aggregation for specific commands:
Please refer to [the documentation within the code](https://github.com/valkey-io/valkey-glide-csharp/blob/main/sources/Valkey.Glide/ClusterValue.cs) for cluster response types.
+
+
+ Please refer to the documentation within the code.
+
### Topology Updates
@@ -306,6 +325,19 @@ Valkey GLIDE also supports Standalone deployments, where the database is hosted
await using var client = await GlideClient.CreateClient(config);
```
+
+
+ ```ruby
+ require "valkey"
+
+ # The Ruby client connects to a single standalone address.
+ # Use the read_from option to route reads to replicas.
+ client = Valkey.new(host: "primary.example.com", port: 6379)
+
+ # Or connect with a URL
+ client = Valkey.new(url: "redis://primary.example.com:6379/0")
+ ```
+
## Configuration Options
diff --git a/src/content/docs/how-to/connections/configure-lazy-connection.mdx b/src/content/docs/how-to/connections/configure-lazy-connection.mdx
index 5b1bb92f..62929244 100644
--- a/src/content/docs/how-to/connections/configure-lazy-connection.mdx
+++ b/src/content/docs/how-to/connections/configure-lazy-connection.mdx
@@ -189,6 +189,34 @@ Lazy connection can be configured through the client configuration object.
$clusterClient->close();
```
+
+
+ ```ruby
+ require "valkey"
+
+ # Standalone client with lazy connect
+ standalone_client = Valkey.new(
+ host: "localhost",
+ port: 6379,
+ lazy_connect: true,
+ timeout: 5.0
+ )
+
+ # Cluster client with lazy connect
+ cluster_client = Valkey.new(
+ nodes: [
+ { host: "localhost", port: 7000 },
+ { host: "localhost", port: 7001 }
+ ],
+ cluster_mode: true,
+ lazy_connect: true,
+ timeout: 5.0
+ )
+
+ # No connection established yet - this will trigger the connection
+ result = standalone_client.ping
+ ```
+
## How It Works
diff --git a/src/content/docs/how-to/connections/limit-inflight-requests.mdx b/src/content/docs/how-to/connections/limit-inflight-requests.mdx
index 202ae33b..5e452649 100644
--- a/src/content/docs/how-to/connections/limit-inflight-requests.mdx
+++ b/src/content/docs/how-to/connections/limit-inflight-requests.mdx
@@ -58,6 +58,17 @@ Inflight requests limit can be configured through the general client configurati
)
```
+
+
+ ```ruby
+ # Limit to 1000 inflight requests per connection
+ client = Valkey.new(
+ nodes: [{ host: "localhost", port: 7000 }],
+ cluster_mode: true,
+ inflight_requests_limit: 1000
+ )
+ ```
+
## Why Limit Inflight Requests
diff --git a/src/content/docs/how-to/connections/read-strategy.mdx b/src/content/docs/how-to/connections/read-strategy.mdx
index 2e9e6772..386494cd 100644
--- a/src/content/docs/how-to/connections/read-strategy.mdx
+++ b/src/content/docs/how-to/connections/read-strategy.mdx
@@ -141,6 +141,22 @@ Valkey GLIDE provides support for the following read strategies, allowing you to
$client->get('key1');
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true,
+ read_from: Valkey::ReadFrom::PREFER_REPLICA
+ )
+
+ client.set("key1", "val1")
+ # get will read from one of the replicas
+ client.get("key1")
+ ```
+
### AZ Affinity
@@ -272,6 +288,23 @@ When using the AZ Affinity read strategy, the `clientAz` setting is required to
$client->get('key1');
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true,
+ read_from: Valkey::ReadFrom::AZ_AFFINITY,
+ client_az: "us-east-1a"
+ )
+
+ client.set("key1", "val1")
+ # get will read from one of the replicas in the same client's availability zone if they exist
+ client.get("key1")
+ ```
+
### AZ Affinity Replicas and Primary Read Strategy
@@ -403,4 +436,21 @@ When using the AZ Affinity Replicas and Primary read strategy, the `clientAz` se
$client->get('key1');
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true,
+ read_from: Valkey::ReadFrom::AZ_AFFINITY_REPLICAS_AND_PRIMARY,
+ client_az: "us-east-1a"
+ )
+
+ client.set("key1", "val1")
+ # get will read from one of the replicas or the primary in the same client's availability zone if they exist
+ client.get("key1")
+ ```
+
diff --git a/src/content/docs/how-to/connections/resilience-best-practices.mdx b/src/content/docs/how-to/connections/resilience-best-practices.mdx
index b744d702..7977deb4 100644
--- a/src/content/docs/how-to/connections/resilience-best-practices.mdx
+++ b/src/content/docs/how-to/connections/resilience-best-practices.mdx
@@ -12,80 +12,92 @@ This guide covers configuration and operational practices that help Valkey GLIDE
A resilient client combines request timeout, inflight limiting, and the circuit breaker:
-
-
-```python
-from glide import (
- GlideClusterClient,
- GlideClusterClientConfiguration,
- ClientCircuitBreakerConfiguration,
- NodeAddress,
-)
-
-config = GlideClusterClientConfiguration(
- addresses=[NodeAddress(host="localhost", port=6379)],
- request_timeout=500,
- inflight_requests_limit=1000,
- client_circuit_breaker=ClientCircuitBreakerConfiguration(),
-)
-client = await GlideClusterClient.create(config)
-```
-
-
-
-
-```java
-import glide.api.GlideClusterClient;
-import glide.api.models.configuration.GlideClusterClientConfiguration;
-import glide.api.models.configuration.ClientCircuitBreakerConfiguration;
-import glide.api.models.configuration.NodeAddress;
-
-GlideClusterClient client = GlideClusterClient.createClient(
- GlideClusterClientConfiguration.builder()
- .address(NodeAddress.builder().host("localhost").port(6379).build())
- .requestTimeout(500)
- .inflightRequestsLimit(1000)
- .clientCircuitBreakerConfiguration(
- ClientCircuitBreakerConfiguration.builder().build())
- .build()
-).get();
-```
-
-
-
-
-```typescript
-import { GlideClusterClient } from "@valkey/valkey-glide";
-
-const client = await GlideClusterClient.createClient({
- addresses: [{ host: "localhost", port: 6379 }],
- requestTimeout: 500,
- inflightRequestsLimit: 1000,
- clientCircuitBreaker: {},
-});
-```
-
-
-
-
-```go
-import (
- "time"
-
- glide "github.com/valkey-io/valkey-glide/go/v2"
- "github.com/valkey-io/valkey-glide/go/v2/config"
-)
-
-clientConfig := config.NewClusterClientConfiguration().
- WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379}).
- WithRequestTimeout(500 * time.Millisecond).
- WithInflightRequestsLimit(1000).
- WithClientCircuitBreaker(&config.ClientCircuitBreakerConfiguration{})
-
-client, err := glide.NewClusterClient(clientConfig)
-```
-
-
+
+ ```python
+ from glide import (
+ GlideClusterClient,
+ GlideClusterClientConfiguration,
+ ClientCircuitBreakerConfiguration,
+ NodeAddress,
+ )
+
+ config = GlideClusterClientConfiguration(
+ addresses=[NodeAddress(host="localhost", port=6379)],
+ request_timeout=500,
+ inflight_requests_limit=1000,
+ client_circuit_breaker=ClientCircuitBreakerConfiguration(),
+ )
+ client = await GlideClusterClient.create(config)
+ ```
+
+
+
+ ```java
+ import glide.api.GlideClusterClient;
+ import glide.api.models.configuration.GlideClusterClientConfiguration;
+ import glide.api.models.configuration.ClientCircuitBreakerConfiguration;
+ import glide.api.models.configuration.NodeAddress;
+
+ GlideClusterClient client = GlideClusterClient.createClient(
+ GlideClusterClientConfiguration.builder()
+ .address(NodeAddress.builder().host("localhost").port(6379).build())
+ .requestTimeout(500)
+ .inflightRequestsLimit(1000)
+ .clientCircuitBreakerConfiguration(
+ ClientCircuitBreakerConfiguration.builder().build())
+ .build()
+ ).get();
+ ```
+
+
+
+ ```typescript
+ import { GlideClusterClient } from "@valkey/valkey-glide";
+
+ const client = await GlideClusterClient.createClient({
+ addresses: [{ host: "localhost", port: 6379 }],
+ requestTimeout: 500,
+ inflightRequestsLimit: 1000,
+ clientCircuitBreaker: {},
+ });
+ ```
+
+
+
+ ```go
+ import (
+ "time"
+
+ glide "github.com/valkey-io/valkey-glide/go/v2"
+ "github.com/valkey-io/valkey-glide/go/v2/config"
+ )
+
+ clientConfig := config.NewClusterClientConfiguration().
+ WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379}).
+ WithRequestTimeout(500 * time.Millisecond).
+ WithInflightRequestsLimit(1000).
+ WithClientCircuitBreaker(&config.ClientCircuitBreakerConfiguration{})
+
+ client, err := glide.NewClusterClient(clientConfig)
+ ```
+
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "localhost", port: 6379 }],
+ cluster_mode: true,
+ timeout: 0.5, # request timeout in seconds (500 ms)
+ inflight_requests_limit: 1000
+ )
+ ```
+
+ :::note
+ The client circuit breaker is not yet available in GLIDE Ruby.
+ :::
+
## Single Client Instance
@@ -111,11 +123,11 @@ The `inflightRequestsLimit` controls how many concurrent requests a single clien
**Key points:**
-- The inflight limit should accommodate your expected concurrency: at throughput `T` ops/s with average latency `L` seconds, you need roughly `T × L` inflight slots (e.g., 50k ops/s at 1ms = ~50 slots, 50k ops/s at 10ms = ~500 slots).
-- When the limit is reached, new requests block until a slot frees up. The circuit breaker (if enabled) rejects before this blocking occurs.
-- If using Java with `ForkJoinPool.managedBlock()` (common in Akka, Play, or reactive frameworks), set the limit to 2-3x your thread pool size. This prevents thread explosion where `managedBlock()` spawns compensating threads faster than requests complete.
-- If you see "inflight requests limit reached" warnings in logs, either increase the limit or reduce concurrency at the application level.
-- Setting the limit too high risks memory pressure under sustained backpressure. The default of 1000 is appropriate for most workloads.
+* The inflight limit should accommodate your expected concurrency: at throughput `T` ops/s with average latency `L` seconds, you need roughly `T × L` inflight slots (e.g., 50k ops/s at 1ms = ~50 slots, 50k ops/s at 10ms = ~500 slots).
+* When the limit is reached, new requests block until a slot frees up. The circuit breaker (if enabled) rejects before this blocking occurs.
+* If using Java with `ForkJoinPool.managedBlock()` (common in Akka, Play, or reactive frameworks), set the limit to 2-3x your thread pool size. This prevents thread explosion where `managedBlock()` spawns compensating threads faster than requests complete.
+* If you see "inflight requests limit reached" warnings in logs, either increase the limit or reduce concurrency at the application level.
+* Setting the limit too high risks memory pressure under sustained backpressure. The default of 1000 is appropriate for most workloads.
## Thread Pool Sizing (Java)
@@ -168,11 +180,11 @@ See the dedicated [Circuit Breaker guide](/how-to/connections/circuit-breaker) f
**Key points:**
-- Enable CB for workloads where thread exhaustion is a concern during outages.
-- The CB rejects before the request reaches the network, so rejections are near-zero-cost.
-- Enable `countTimeouts` to protect against dead or unreachable nodes. In cluster mode, dead nodes surface primarily as timeouts, so this flag is required for the CB to trip on sustained node outages.
-- Recovery is optimistic: in HalfOpen, all traffic is allowed through. After consecutive successes the breaker closes. If a failure occurs, it returns to Open.
-- When the CB rejects, handle the `CircuitBreakerException`/`CircuitBreakerError` in your application by returning a cached or degraded response, or signaling the caller to retry after a delay.
+* Enable CB for workloads where thread exhaustion is a concern during outages.
+* The CB rejects before the request reaches the network, so rejections are near-zero-cost.
+* Enable `countTimeouts` to protect against dead or unreachable nodes. In cluster mode, dead nodes surface primarily as timeouts, so this flag is required for the CB to trip on sustained node outages.
+* Recovery is optimistic: in HalfOpen, all traffic is allowed through. After consecutive successes the breaker closes. If a failure occurs, it returns to Open.
+* When the CB rejects, handle the `CircuitBreakerException`/`CircuitBreakerError` in your application by returning a cached or degraded response, or signaling the caller to retry after a delay.
## Standalone vs Cluster
diff --git a/src/content/docs/how-to/connections/timeouts-and-reconnect-strategy.mdx b/src/content/docs/how-to/connections/timeouts-and-reconnect-strategy.mdx
index 7074974b..c9fcd227 100644
--- a/src/content/docs/how-to/connections/timeouts-and-reconnect-strategy.mdx
+++ b/src/content/docs/how-to/connections/timeouts-and-reconnect-strategy.mdx
@@ -111,6 +111,18 @@ Valkey GLIDE allows you to configure timeout settings and reconnect strategies.
await using var client = await GlideClusterClient.CreateClient(config);
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true,
+ timeout: 0.5 # request timeout in seconds (500 ms)
+ )
+ ```
+
## Setting Connection Timeout
@@ -212,6 +224,18 @@ The connection timeout controls how long the client waits for a TCP/TLS connecti
await using var client = await GlideClusterClient.CreateClient(config);
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true,
+ connect_timeout: 5.0 # connection timeout in seconds (5000 ms)
+ )
+ ```
+
## Configuring Reconnect Strategy
@@ -336,4 +360,20 @@ The connection timeout controls how long the client waits for a TCP/TLS connecti
await using var client = await GlideClient.CreateClient(config);
```
+
+
+ ```ruby
+ require "valkey"
+
+ # GLIDE derives an exponential backoff strategy from these
+ # redis-rb-style options (delays are in seconds)
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true,
+ reconnect_attempts: 3,
+ reconnect_delay: 0.5,
+ reconnect_delay_max: 5.0
+ )
+ ```
+
diff --git a/src/content/docs/how-to/execute-custom-commands.mdx b/src/content/docs/how-to/execute-custom-commands.mdx
index e6eb8617..4c548672 100644
--- a/src/content/docs/how-to/execute-custom-commands.mdx
+++ b/src/content/docs/how-to/execute-custom-commands.mdx
@@ -155,6 +155,28 @@ Pass the command name and arguments as an array of strings:
Console.WriteLine(result); // hello
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(host: "localhost", port: 6379)
+
+ # Execute a SET command
+ client.call("SET", "mykey", "hello")
+
+ # Execute a GET command
+ result = client.call("GET", "mykey")
+ puts result # hello
+
+ # call_v takes the whole command as a single array —
+ # useful when the command is built dynamically
+ result = client.call_v(["MGET", "mykey"])
+ puts result.inspect # ["hello"]
+
+ client.close
+ ```
+
## Limitations
diff --git a/src/content/docs/how-to/execute-custom-scripts.mdx b/src/content/docs/how-to/execute-custom-scripts.mdx
index 874a30d9..e8fc1e47 100644
--- a/src/content/docs/how-to/execute-custom-scripts.mdx
+++ b/src/content/docs/how-to/execute-custom-scripts.mdx
@@ -380,6 +380,65 @@ The following steps shows how to run a simple a custom Lua script using GLIDE.
Other GLIDE clients provide a `Script` API that automatically handles script caching and SHA1 management. In PHP, you manually manage this using `eval()` and `evalsha()`. For detailed patterns and best practices, see the [Valkey Scripting Reference](/reference/scripting-reference).
:::
+
+
+
+ 1. Define the lua script
+
+ ```ruby
+ lua = <<~LUA
+ server.call('SET', KEYS[1], ARGV[1])
+ return KEYS[1] .. ': ' .. server.call('GET', KEYS[1])
+ LUA
+ ```
+
+ 2. Execute the script with keys and arguments using `eval`
+
+ ```ruby
+ keys = ["username"]
+ args = ["John Doe"]
+ result = client.eval(lua, keys: keys, args: args)
+ puts result # username: John Doe
+ ```
+
+
+
+ Full Example
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(host: "localhost", port: 6379)
+
+ lua = <<~LUA
+ server.call('SET', KEYS[1], ARGV[1])
+ return KEYS[1] .. ': ' .. server.call('GET', KEYS[1])
+ LUA
+
+ keys = ["username"]
+ args = ["John Doe"]
+ result = client.eval(lua, keys: keys, args: args)
+ puts result
+
+ client.close
+ ```
+
+
+ ### Using script\_load and evalsha for Repeated Execution
+
+ For scripts executed multiple times, load the script once with `script_load` and execute it by its SHA1 hash:
+
+ ```ruby
+ sha = client.script_load(lua)
+
+ result = client.evalsha(sha, keys: ["username"], args: ["John Doe"])
+ puts result # username: John Doe
+
+ # invoke_script is equivalent and also takes the SHA1 hash
+ result = client.invoke_script(sha, keys: ["username"], args: ["John Doe"])
+ puts result # username: John Doe
+ ```
+
## What's Next
diff --git a/src/content/docs/how-to/installation.mdx b/src/content/docs/how-to/installation.mdx
index 12512db3..ed84f6b3 100644
--- a/src/content/docs/how-to/installation.mdx
+++ b/src/content/docs/how-to/installation.mdx
@@ -325,4 +325,30 @@ Windows support is currently available for Valkey GLIDE Java and C#.
dotnet add package Valkey.Glide
```
+
+
+ **Requirements:** Ruby 2.6+ (MRI) or JRuby 3.0+
+
+ To get started, Valkey GLIDE Ruby is available on [RubyGems](https://rubygems.org/gems/valkey-glide-rb).
+
+ ```bash
+ gem install valkey-glide-rb
+ ```
+
+ Or add it to your `Gemfile`:
+
+ ```ruby
+ gem "valkey-glide-rb"
+ ```
+
+ Verify installation:
+
+ ```bash
+ ruby -e 'require "valkey"; puts Valkey::VERSION'
+ ```
+
+ :::note
+ The gem ships prebuilt native libraries for Linux and macOS, including Alpine Linux / musl (3.18+), and depends on the [`ffi`](https://github.com/ffi/ffi) gem.
+ :::
+
diff --git a/src/content/docs/how-to/load-and-execute-functions.mdx b/src/content/docs/how-to/load-and-execute-functions.mdx
index 9bab4d8a..d5cdc1b1 100644
--- a/src/content/docs/how-to/load-and-execute-functions.mdx
+++ b/src/content/docs/how-to/load-and-execute-functions.mdx
@@ -409,6 +409,65 @@ The following example shows a simple example of loading and executing a Valkey F
```
+
+
+
+ 1. Define the lua script.
+
+ ```ruby
+ lua_code = <<~LUA
+ #!lua name=example_module
+ server.register_function('set_then_get', function(key, value)
+ server.call('SET', key, value)
+ return server.call('GET', key)
+ end)
+ LUA
+ ```
+
+ 2. Load the function to Valkey.
+
+ ```ruby
+ client.function_load(lua_code, replace: true)
+ ```
+
+ 3. Call the function.
+
+ ```ruby
+ client.set("page:home:visits", "0")
+ result = client.fcall("set_then_get", keys: ["page:home:visits"], args: ["1"])
+ puts result # 1
+ ```
+
+
+
+ Full Example
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(host: "localhost", port: 6379)
+
+ # lua code that updates a key and returns its new value
+ lua_code = <<~LUA
+ #!lua name=page_visits
+ server.register_function('update_visits', function(visits)
+ server.call('INCR', visits[1])
+ return server.call('GET', visits[1])
+ end)
+ LUA
+
+ # loading the function to valkey
+ client.function_load(lua_code, replace: true)
+
+ client.set("page:home:visits", "0")
+ # calling the previously loaded function
+ result = client.fcall("update_visits", keys: ["page:home:visits"])
+ puts result # 1
+
+ client.close
+ ```
+
+
## Read-Only Functions
@@ -543,6 +602,25 @@ GLIDE clients implement `FCALL_RO` command to execute read-only functions.
$result = $client->fcall_ro('get_value', [], [], 'randomNode');
```
+
+
+ ```ruby
+ result = client.fcall_ro("get_value", keys: ["mykey"])
+ ```
+
+ **With Routing (Cluster Mode)**
+
+ ```ruby
+ # Route to all nodes
+ result = client.fcall_ro("get_value", route: Valkey::Route.all_nodes)
+
+ # Route to all primary nodes
+ result = client.fcall_ro("get_value", route: Valkey::Route.all_primaries)
+
+ # Route to a random node
+ result = client.fcall_ro("get_value", route: Valkey::Route.random)
+ ```
+
## What's Next
diff --git a/src/content/docs/how-to/modules-api/json-module.mdx b/src/content/docs/how-to/modules-api/json-module.mdx
index 418cec68..eb66abea 100644
--- a/src/content/docs/how-to/modules-api/json-module.mdx
+++ b/src/content/docs/how-to/modules-api/json-module.mdx
@@ -176,6 +176,29 @@ Use `INFO MODULES` or `MODULE LIST` command to see the status of all loaded modu
Console.WriteLine($"Output: {response}"); // Output: {"a":1.0,"b":2}
```
+
+
+ ```ruby
+ require "valkey"
+ require "json"
+
+ # Both standalone and cluster mode are supported
+ client = Valkey.new(host: "localhost", port: 6379)
+
+ key = "testKey"
+ path = "$"
+ json_value = '{"a": 1.0, "b": 2}'
+
+ # JSON.SET
+ set_response = client.json_set(key, path, json_value)
+ # set_response == "OK"
+
+ # JSON.GET
+ get_response = client.json_get(key, "$")
+ # get_response == '[{"a":1.0,"b":2}]'
+ JSON.parse(get_response) # => [{"a" => 1.0, "b" => 2}]
+ ```
+
## What's Next
diff --git a/src/content/docs/how-to/modules-api/search-module.mdx b/src/content/docs/how-to/modules-api/search-module.mdx
index 4db293e9..c0f54b45 100644
--- a/src/content/docs/how-to/modules-api/search-module.mdx
+++ b/src/content/docs/how-to/modules-api/search-module.mdx
@@ -360,6 +360,39 @@ Use `INFO MODULES` or `MODULE LIST` command to see the status of all loaded modu
Console.WriteLine($"Vectors: [{string.Join(", ", vectors)}]"); // Vectors: [0000000000000000, 00000000000080BF]
```
+
+
+ ```ruby
+ require "valkey"
+
+ # Both standalone and cluster mode are supported
+ client = Valkey.new(host: "localhost", port: 6379)
+
+ prefix = "{hash}:"
+ index = prefix + "index"
+
+ # FT.CREATE a Hash index with a vector field
+ client.ft_create(index, "ON", "HASH", "PREFIX", "1", prefix,
+ "SCHEMA", "vec", "AS", "VEC", "VECTOR", "HNSW", "6",
+ "TYPE", "FLOAT32", "DIM", "2", "DISTANCE_METRIC", "L2")
+ # => "OK"
+
+ # Insert hash data with vector fields (2-dimensional float32 vectors = 8 bytes each)
+ vec0 = [0.0, 0.0].pack("e2") # "\x00\x00\x00\x00\x00\x00\x00\x00"
+ vec1 = [0.0, -1.0].pack("e2") # "\x00\x00\x00\x00\x00\x00\x80\xBF"
+ client.hset(prefix + "0", "vec", vec0)
+ client.hset(prefix + "1", "vec", vec1)
+
+ sleep 1 # let server digest the data and update index
+
+ # FT.SEARCH
+ result = client.ft_search(index, "*=>[KNN 2 @VEC $query_vec]",
+ "PARAMS", "2", "query_vec", vec0,
+ "DIALECT", "2")
+ # result[0] == 2
+ # the remaining entries contain "{hash}:0" and "{hash}:1" with their vector values
+ ```
+
## What's Next
diff --git a/src/content/docs/how-to/monitoring/open-telemetry.mdx b/src/content/docs/how-to/monitoring/open-telemetry.mdx
index 7ea8705e..2ca79b27 100644
--- a/src/content/docs/how-to/monitoring/open-telemetry.mdx
+++ b/src/content/docs/how-to/monitoring/open-telemetry.mdx
@@ -159,6 +159,26 @@ GLIDE does not export data directly to third-party services—instead, it sends
);
```
+
+
+ ```ruby
+ require "valkey"
+
+ # Initialize once per process, before creating clients
+ Valkey::OpenTelemetry.init(
+ traces: {
+ endpoint: "http://localhost:4318/v1/traces",
+ sample_percentage: 10 # Optional, defaults to 1
+ },
+ metrics: {
+ endpoint: "http://localhost:4318/v1/metrics"
+ },
+ flush_interval_ms: 1000 # Optional, defaults to 5000
+ )
+
+ client = Valkey.new(host: "localhost", port: 6379)
+ ```
+
:::tip
diff --git a/src/content/docs/how-to/monitoring/tracking-resources.mdx b/src/content/docs/how-to/monitoring/tracking-resources.mdx
index afcb271c..560ab981 100644
--- a/src/content/docs/how-to/monitoring/tracking-resources.mdx
+++ b/src/content/docs/how-to/monitoring/tracking-resources.mdx
@@ -130,4 +130,23 @@ GLIDE 1.2 introduces a new non-Valkey API: `getStatistics` which returns statist
echo "Total Clients: {$stats['total_clients']}\n";
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ nodes: [{ host: "address.example.com", port: 6379 }],
+ cluster_mode: true,
+ timeout: 0.5 # request timeout in seconds (500 ms)
+ )
+
+ # Retrieve statistics
+ stats = client.get_statistics
+
+ # Example: Accessing and printing statistics
+ puts "Total Connections: #{stats[:total_connections]}"
+ puts "Total Clients: #{stats[:total_clients]}"
+ ```
+
diff --git a/src/content/docs/how-to/security/authentication.mdx b/src/content/docs/how-to/security/authentication.mdx
index 41310745..852d8c15 100644
--- a/src/content/docs/how-to/security/authentication.mdx
+++ b/src/content/docs/how-to/security/authentication.mdx
@@ -124,6 +124,25 @@ Both standalone and cluster mode support authentication authentication with user
$client->connect(addresses: $addresses, credentials: $credentials);
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ host: "primary.example.com",
+ port: 6379,
+ username: "user1",
+ password: "passwordA"
+ )
+ ```
+
+ Credentials can also be embedded in a connection URL:
+
+ ```ruby
+ client = Valkey.new(url: "redis://user1:passwordA@primary.example.com:6379")
+ ```
+
### Cluster
@@ -225,6 +244,21 @@ Both standalone and cluster mode support authentication authentication with user
);
```
+
+
+ ```ruby
+ require "valkey"
+
+ nodes = [{ host: "address.example.com", port: 6379 }]
+
+ client = Valkey.new(
+ nodes: nodes,
+ cluster_mode: true,
+ username: "user1",
+ password: "passwordA"
+ )
+ ```
+
## Best Practices
diff --git a/src/content/docs/how-to/security/tls.mdx b/src/content/docs/how-to/security/tls.mdx
index 07a85598..2201b77a 100644
--- a/src/content/docs/how-to/security/tls.mdx
+++ b/src/content/docs/how-to/security/tls.mdx
@@ -110,6 +110,16 @@ Enabling TLS is as simple as setting `use_tls=True` in your configuration. The c
);
```
+
+
+ ```ruby
+ require "valkey"
+
+ nodes = [{ host: "address.example.com", port: 6379 }]
+
+ client = Valkey.new(nodes: nodes, cluster_mode: true, ssl: true)
+ ```
+
### Standalone
@@ -215,6 +225,20 @@ Enabling TLS is as simple as setting `use_tls=True` in your configuration. The c
$client->connect(addresses: $addresses, use_tls: true);
```
+
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(host: "primary.example.com", port: 6379, ssl: true)
+ ```
+
+ A `rediss://` URL enables TLS as well:
+
+ ```ruby
+ client = Valkey.new(url: "rediss://primary.example.com:6379")
+ ```
+
## Advanced TLS Configurations
@@ -527,6 +551,60 @@ You can provide custom root certificates for TLS connections. This is useful whe
);
```
+
+
+ **Certificate Behavior:**
+
+ * If `ssl_params` is not provided, the system's default certificate trust store is used
+ * `ca_file` takes a path to a CA certificate file in PEM format
+ * Multiple certificates can be provided as PEM strings via the `root_certs` array, or by pointing `ca_path` at a directory of `.crt`/`.pem` files
+
+ #### Example - Connecting with Custom Root Certificate from File
+
+ ```ruby
+ require "valkey"
+
+ client = Valkey.new(
+ host: "address.example.com",
+ port: 6379,
+ ssl: true,
+ ssl_params: { ca_file: "/path/to/ca-cert.pem" }
+ )
+ ```
+
+ #### Example - Using Certificate as String
+
+ ```ruby
+ cert_data = <<~CERT
+ -----BEGIN CERTIFICATE-----
+ MIIDXTCCAkWgAwIBAgIJAKL0UG+mRKmzMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+ ...
+ -----END CERTIFICATE-----
+ CERT
+
+ client = Valkey.new(
+ host: "address.example.com",
+ port: 6379,
+ ssl: true,
+ ssl_params: { root_certs: [cert_data] }
+ )
+ ```
+
+ #### Example - Client Certificate (Mutual TLS)
+
+ ```ruby
+ client = Valkey.new(
+ host: "address.example.com",
+ port: 6379,
+ ssl: true,
+ ssl_params: {
+ ca_file: "/path/to/ca-cert.pem",
+ cert: "/path/to/client-cert.pem",
+ key: "/path/to/client-key.pem"
+ }
+ )
+ ```
+
### TLS Certificate Format
diff --git a/src/content/docs/how-to/send-batch-commands.mdx b/src/content/docs/how-to/send-batch-commands.mdx
index 82b153a9..5e39d780 100644
--- a/src/content/docs/how-to/send-batch-commands.mdx
+++ b/src/content/docs/how-to/send-batch-commands.mdx
@@ -226,6 +226,41 @@ A transaction is an all-or-nothing set of commands sent in a single request to V
// Atomic Batch Results: OK, OK, 50, 50, 50
```
+
+
+ ```ruby
+ require "valkey"
+
+ # Initialize client
+ client = Valkey.new(host: "localhost", port: 6379)
+
+ # Create an atomic transaction using multi
+ results = client.multi do |tx|
+ tx.set("account:source", "100")
+ tx.set("account:dest", "0")
+ tx.incrby("account:dest", 50)
+ tx.decrby("account:source", 50)
+ tx.get("account:source")
+ end
+
+ puts "Atomic Transaction Results: #{results.inspect}"
+ # Atomic Transaction Results: ["OK", "OK", 50, 50, "50"]
+ ```
+
+ Use `watch` / `unwatch` for optimistic locking around a transaction:
+
+ ```ruby
+ client.watch("account:source") do
+ if client.get("account:source") == "100"
+ client.multi do |tx|
+ tx.decrby("account:source", 50)
+ end
+ else
+ client.unwatch
+ end
+ end
+ ```
+
### Cluster
@@ -433,6 +468,26 @@ A transaction is an all-or-nothing set of commands sent in a single request to V
// Atomic Cluster Batch: OK, 6, 6
```
+
+
+ ```ruby
+ require "valkey"
+
+ # Initialize cluster client
+ nodes = [{ host: "127.0.0.1", port: 6379 }]
+ client = Valkey.new(nodes: nodes, cluster_mode: true)
+
+ # Create an atomic transaction (all keys map to same slot)
+ results = client.multi do |tx|
+ tx.set("user:100:visits", "1")
+ tx.incrby("user:100:visits", 5)
+ tx.get("user:100:visits")
+ end
+
+ puts "Atomic Cluster Transaction: #{results.inspect}"
+ # Atomic Cluster Transaction: ["OK", 6, "6"]
+ ```
+
:::caution[Important]
@@ -627,6 +682,26 @@ Pipelining is a group of commands sent in a single request that does not guarant
// Pipeline Results: OK, OK, value1, value2
```
+
+
+ ```ruby
+ require "valkey"
+
+ # Initialize client
+ client = Valkey.new(host: "localhost", port: 6379)
+
+ # Create non-atomic pipeline using pipelined
+ results = client.pipelined do |pipe|
+ pipe.set("temp:key1", "value1")
+ pipe.set("temp:key2", "value2")
+ pipe.get("temp:key1")
+ pipe.get("temp:key2")
+ end
+
+ puts "Pipeline Results: #{results.inspect}"
+ # Pipeline Results: ["OK", "OK", "value1", "value2"]
+ ```
+
### Cluster
@@ -866,6 +941,29 @@ Pipelining is a group of commands sent in a single request that does not guarant
// Pipeline Cluster Results: OK, 125, 125, 1, 2, [user2, user1]
```
+
+
+ ```ruby
+ require "valkey"
+
+ # Initialize cluster client
+ nodes = [{ host: "localhost", port: 6379 }]
+ client = Valkey.new(nodes: nodes, cluster_mode: true)
+
+ # Create pipeline spanning multiple slots
+ results = client.pipelined do |pipe|
+ pipe.set("page:home:views", "100")
+ pipe.incrby("page:home:views", 25)
+ pipe.get("page:home:views")
+ pipe.lpush("recent:logins", "user1")
+ pipe.lpush("recent:logins", "user2")
+ pipe.lrange("recent:logins", 0, 1)
+ end
+
+ puts "Pipeline Cluster Results: #{results.inspect}"
+ # Pipeline Cluster Results: ["OK", 125, "125", 1, 2, ["user2", "user1"]]
+ ```
+
## Next Steps