valkey-glide-rb 0.9.0.pre.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +69 -0
- data/.rubocop_todo.yml +22 -0
- data/AGENTS.md +224 -0
- data/CLAUDE.md +130 -0
- data/CONTRIBUTING.md +115 -0
- data/DEVELOPER.md +453 -0
- data/README.md +268 -0
- data/Rakefile +126 -0
- data/examples/README.md +55 -0
- data/examples/cluster.rb +24 -0
- data/examples/opentelemetry.rb +50 -0
- data/examples/pipelining.rb +29 -0
- data/examples/standalone.rb +22 -0
- data/examples/statistics.rb +24 -0
- data/lib/valkey/bindings.rb +319 -0
- data/lib/valkey/commands/bitmap_commands.rb +86 -0
- data/lib/valkey/commands/cluster_commands.rb +259 -0
- data/lib/valkey/commands/connection_commands.rb +318 -0
- data/lib/valkey/commands/function_commands.rb +255 -0
- data/lib/valkey/commands/generic_commands.rb +525 -0
- data/lib/valkey/commands/geo_commands.rb +87 -0
- data/lib/valkey/commands/hash_commands.rb +592 -0
- data/lib/valkey/commands/hyper_log_log_commands.rb +51 -0
- data/lib/valkey/commands/json_commands.rb +389 -0
- data/lib/valkey/commands/list_commands.rb +348 -0
- data/lib/valkey/commands/module_commands.rb +125 -0
- data/lib/valkey/commands/pubsub_commands.rb +237 -0
- data/lib/valkey/commands/scripting_commands.rb +287 -0
- data/lib/valkey/commands/server_commands.rb +961 -0
- data/lib/valkey/commands/set_commands.rb +220 -0
- data/lib/valkey/commands/sorted_set_commands.rb +971 -0
- data/lib/valkey/commands/stream_commands.rb +636 -0
- data/lib/valkey/commands/string_commands.rb +371 -0
- data/lib/valkey/commands/transaction_commands.rb +175 -0
- data/lib/valkey/commands/vector_search_commands.rb +271 -0
- data/lib/valkey/commands.rb +68 -0
- data/lib/valkey/errors.rb +41 -0
- data/lib/valkey/native/aarch64-unknown-linux-gnu/libglide_ffi.so +0 -0
- data/lib/valkey/native/x86_64-unknown-linux-gnu/libglide_ffi.so +0 -0
- data/lib/valkey/opentelemetry.rb +207 -0
- data/lib/valkey/pipeline.rb +20 -0
- data/lib/valkey/pubsub_callback.rb +10 -0
- data/lib/valkey/request_error_type.rb +10 -0
- data/lib/valkey/request_type.rb +436 -0
- data/lib/valkey/response_type.rb +20 -0
- data/lib/valkey/utils.rb +267 -0
- data/lib/valkey/version.rb +5 -0
- data/lib/valkey.rb +617 -0
- metadata +107 -0
data/README.md
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Valkey GLIDE for Ruby
|
|
2
|
+
|
|
3
|
+
Valkey General Language Independent Driver for the Enterprise (GLIDE) is the official open-source Valkey client library, proudly part of the [Valkey](https://valkey.io) organization. The Ruby gem (`valkey-rb`) wraps [Valkey GLIDE Core](https://github.com/valkey-io/valkey-glide) (Rust) and aims to be a **drop-in replacement for [redis-rb](https://github.com/redis/redis-rb)** while delivering GLIDE performance, reliability, and enterprise features.
|
|
4
|
+
|
|
5
|
+
## Why Choose Valkey GLIDE?
|
|
6
|
+
|
|
7
|
+
- **Community and Open Source**: Join our vibrant community and contribute to the project.
|
|
8
|
+
- **Reliability**: Built with best practices learned from over a decade of operating Redis OSS-compatible services.
|
|
9
|
+
- **Performance**: Optimized for high performance and low latency via the Rust-based GLIDE core.
|
|
10
|
+
- **High Availability**: Cluster-aware routing, reconnection, and fault tolerance.
|
|
11
|
+
- **Cross-Language Consistency**: Same core driver as Python, Java, Node.js, and Go clients.
|
|
12
|
+
- **Drop-in Replacement**: Familiar redis-rb-style API (`Valkey.new`, command methods, `pipelined`, URL parsing).
|
|
13
|
+
- **Observability**: Native OpenTelemetry tracing and client statistics.
|
|
14
|
+
|
|
15
|
+
## Documentation
|
|
16
|
+
|
|
17
|
+
- **Command coverage**: [Implementation status wiki](https://github.com/valkey-io/valkey-glide-ruby/wiki/The-implementation-status-of-the-Valkey-commands)
|
|
18
|
+
- **Valkey GLIDE overview**: [glide.valkey.io](https://glide.valkey.io/)
|
|
19
|
+
- **Supported engine versions**: [valkey-glide README — Supported Engine Versions](https://github.com/valkey-io/valkey-glide/blob/main/README.md#supported-engine-versions)
|
|
20
|
+
- **Local development**: [DEVELOPER.md](./DEVELOPER.md)
|
|
21
|
+
|
|
22
|
+
## Supported Engine Versions
|
|
23
|
+
|
|
24
|
+
| Engine Type | 6.2 | 7.0 | 7.1 | 7.2 | 8.0 | 8.1 | 9.0 |
|
|
25
|
+
|-------------|-----|-----|-----|-----|-----|-----|-----|
|
|
26
|
+
| Valkey | - | - | - | ✓ | ✓ | ✓ | ✓ |
|
|
27
|
+
| Redis OSS | ✓ | ✓ | ✓ | ✓ | - | - | - |
|
|
28
|
+
|
|
29
|
+
## Getting Started — Ruby Wrapper
|
|
30
|
+
|
|
31
|
+
### System Requirements
|
|
32
|
+
|
|
33
|
+
The release of Valkey GLIDE Ruby was tested on the following platforms:
|
|
34
|
+
|
|
35
|
+
**Linux:**
|
|
36
|
+
|
|
37
|
+
- Ubuntu 20+ (x86_64/amd64 and arm64/aarch64)
|
|
38
|
+
- Amazon Linux 2 (AL2) and 2023 (AL2023) (x86_64)
|
|
39
|
+
|
|
40
|
+
**Note:** Alpine Linux / MUSL is **not** currently supported.
|
|
41
|
+
|
|
42
|
+
**macOS:**
|
|
43
|
+
|
|
44
|
+
- macOS 14.7+ (Apple silicon / aarch64)
|
|
45
|
+
- macOS 13.7+ (x86_64 / amd64)
|
|
46
|
+
|
|
47
|
+
### Ruby Supported Versions
|
|
48
|
+
|
|
49
|
+
| Ruby Version | MRI | JRuby |
|
|
50
|
+
|--------------|-----|-------|
|
|
51
|
+
| 2.6 | ✓ | - |
|
|
52
|
+
| 2.7 | ✓ | - |
|
|
53
|
+
| 3.0 – 3.4 | ✓ | ✓ |
|
|
54
|
+
|
|
55
|
+
Minimum Ruby version: **2.6.0** (see `valkey.gemspec`).
|
|
56
|
+
|
|
57
|
+
### Installation and Setup
|
|
58
|
+
|
|
59
|
+
Install from RubyGems:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
gem install valkey-rb
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or add to your `Gemfile`:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
gem "valkey-rb"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Verify installation:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
ruby -e 'require "valkey"; puts Valkey::VERSION'
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The gem ships prebuilt native libraries (`libglide_ffi.so` on Linux, `libglide_ffi.dylib` on macOS) and depends on the [`ffi`](https://github.com/ffi/ffi) gem.
|
|
78
|
+
|
|
79
|
+
## Basic Examples
|
|
80
|
+
|
|
81
|
+
### Standalone Mode
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
require "valkey"
|
|
85
|
+
|
|
86
|
+
client = Valkey.new(host: "localhost", port: 6379)
|
|
87
|
+
|
|
88
|
+
client.set("mykey", "hello world")
|
|
89
|
+
# => "OK"
|
|
90
|
+
|
|
91
|
+
client.get("mykey")
|
|
92
|
+
# => "hello world"
|
|
93
|
+
|
|
94
|
+
client.close
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Standalone with URL (redis-rb compatible)
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
client = Valkey.new(url: "redis://localhost:6379/0")
|
|
101
|
+
# TLS: rediss://user:password@localhost:6380/0
|
|
102
|
+
|
|
103
|
+
client.ping
|
|
104
|
+
# => "PONG"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Cluster Mode
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
nodes = [
|
|
111
|
+
{ host: "127.0.0.1", port: 7000 },
|
|
112
|
+
{ host: "127.0.0.1", port: 7001 },
|
|
113
|
+
{ host: "127.0.0.1", port: 7002 },
|
|
114
|
+
{ host: "127.0.0.1", port: 7003 },
|
|
115
|
+
{ host: "127.0.0.1", port: 7004 },
|
|
116
|
+
{ host: "127.0.0.1", port: 7005 }
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
client = Valkey.new(nodes: nodes, cluster_mode: true)
|
|
120
|
+
client.set("foo", "bar")
|
|
121
|
+
client.get("foo")
|
|
122
|
+
# => "bar"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Pipelining
|
|
126
|
+
|
|
127
|
+
Batch multiple commands in a single network round trip (non-atomic pipeline):
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
results = client.pipelined do |pipe|
|
|
131
|
+
pipe.set("key1", "value1")
|
|
132
|
+
pipe.get("key1")
|
|
133
|
+
pipe.incr("counter")
|
|
134
|
+
end
|
|
135
|
+
# => ["OK", "value1", 1]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> **Note:** Transactional commands (`MULTI` / `EXEC` / `DISCARD`) in a pipeline are executed sequentially as a workaround for FFI batch stability. Prefer `multi` / `exec` on the main client for transactions.
|
|
139
|
+
|
|
140
|
+
### Connection Options (redis-rb compatible)
|
|
141
|
+
|
|
142
|
+
| Option | Description |
|
|
143
|
+
|--------|-------------|
|
|
144
|
+
| `host`, `port` | Server address (default `127.0.0.1:6379`) |
|
|
145
|
+
| `url` | `redis://` or `rediss://` URI (merged with explicit options) |
|
|
146
|
+
| `db` | Database index (standalone only) |
|
|
147
|
+
| `password`, `username` | Authentication |
|
|
148
|
+
| `timeout` | Request timeout in seconds (default `5.0`) |
|
|
149
|
+
| `connect_timeout` | Connection timeout in seconds |
|
|
150
|
+
| `ssl`, `ssl_params` | TLS (`ca_file`, `cert`, `key`, `ca_path`, `root_certs`) |
|
|
151
|
+
| `cluster_mode` | Enable cluster client |
|
|
152
|
+
| `nodes` | Array of `{ host:, port: }` hashes |
|
|
153
|
+
| `protocol` | `:resp2` (default) or `:resp3` |
|
|
154
|
+
| `client_name` | `CLIENT SETNAME` value |
|
|
155
|
+
| `reconnect_attempts`, `reconnect_delay`, `reconnect_delay_max` | Connection retry strategy |
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
client = Valkey.new(
|
|
159
|
+
host: "localhost",
|
|
160
|
+
port: 6379,
|
|
161
|
+
timeout: 2.0,
|
|
162
|
+
connect_timeout: 1.0,
|
|
163
|
+
client_name: "my-app",
|
|
164
|
+
protocol: :resp3
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## OpenTelemetry
|
|
169
|
+
|
|
170
|
+
Valkey GLIDE Ruby configures OpenTelemetry in the **native Rust core** (not via the Ruby `opentelemetry-sdk` gem). Initialize once per process before creating clients:
|
|
171
|
+
|
|
172
|
+
```ruby
|
|
173
|
+
require "valkey"
|
|
174
|
+
|
|
175
|
+
Valkey::OpenTelemetry.init(
|
|
176
|
+
traces: {
|
|
177
|
+
endpoint: "http://localhost:4318/v1/traces",
|
|
178
|
+
sample_percentage: 10
|
|
179
|
+
},
|
|
180
|
+
metrics: {
|
|
181
|
+
endpoint: "http://localhost:4318/v1/metrics"
|
|
182
|
+
},
|
|
183
|
+
flush_interval_ms: 5000
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
client = Valkey.new(host: "localhost", port: 6379)
|
|
187
|
+
client.set("key", "value") # traced when sampling applies
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Supported endpoint formats:**
|
|
191
|
+
|
|
192
|
+
- HTTP/HTTPS: `http://localhost:4318/v1/traces`
|
|
193
|
+
- gRPC: `grpc://localhost:4317`
|
|
194
|
+
- File (testing): `file:///tmp/valkey_traces.json`
|
|
195
|
+
|
|
196
|
+
OpenTelemetry can only be initialized **once per process**. Spans are created in the FFI layer when sampling is enabled.
|
|
197
|
+
|
|
198
|
+
## Examples
|
|
199
|
+
|
|
200
|
+
Runnable examples are in [examples/](./examples/):
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
bundle exec ruby examples/standalone.rb
|
|
204
|
+
bundle exec ruby examples/pipelining.rb
|
|
205
|
+
bundle exec ruby examples/opentelemetry.rb
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
See [examples/README.md](./examples/README.md) for cluster setup and environment variables.
|
|
209
|
+
|
|
210
|
+
## Client Statistics
|
|
211
|
+
|
|
212
|
+
Monitor global client metrics (shared across all clients in the process):
|
|
213
|
+
|
|
214
|
+
```ruby
|
|
215
|
+
stats = client.get_statistics
|
|
216
|
+
# alias: client.statistics
|
|
217
|
+
|
|
218
|
+
puts "Connections: #{stats[:total_connections]}"
|
|
219
|
+
puts "Clients: #{stats[:total_clients]}"
|
|
220
|
+
puts "Compressed values: #{stats[:total_values_compressed]}"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Available keys: `:total_connections`, `:total_clients`, `:total_values_compressed`, `:total_values_decompressed`, `:total_original_bytes`, `:total_bytes_compressed`, `:total_bytes_decompressed`, `:compression_skipped_count`.
|
|
224
|
+
|
|
225
|
+
## Pub/Sub
|
|
226
|
+
|
|
227
|
+
Pub/Sub uses a native callback registered at connection time. Configure subscriptions via command modules (`subscribe`, `psubscribe`, etc.). See [DEVELOPER.md](./DEVELOPER.md) and integration tests in `test/valkey/pubsub_commands_test.rb` for details.
|
|
228
|
+
|
|
229
|
+
## Layout of Ruby Code
|
|
230
|
+
|
|
231
|
+
| Path | Purpose |
|
|
232
|
+
|------|---------|
|
|
233
|
+
| `lib/valkey.rb` | Main client: connection, pipelining, response conversion |
|
|
234
|
+
| `lib/valkey/bindings.rb` | FFI bindings to `libglide_ffi` |
|
|
235
|
+
| `lib/valkey/commands/` | Command modules (strings, hashes, streams, cluster, JSON, vector search, …) |
|
|
236
|
+
| `lib/valkey/opentelemetry.rb` | OpenTelemetry configuration |
|
|
237
|
+
| `lib/valkey/pipeline.rb` | Pipeline command batching |
|
|
238
|
+
| `test/valkey/` | Standalone integration tests |
|
|
239
|
+
| `test/cluster/` | Cluster integration tests |
|
|
240
|
+
| `test/lint/` | Shared lint tests (redis-rb compatibility patterns) |
|
|
241
|
+
|
|
242
|
+
## redis-rb Compatibility
|
|
243
|
+
|
|
244
|
+
This client mirrors redis-rb conventions where possible:
|
|
245
|
+
|
|
246
|
+
- `Valkey.new` with `url`, `host`, `port`, `db`, `ssl_params`
|
|
247
|
+
- Command method names and argument ordering aligned with redis-rb
|
|
248
|
+
- `pipelined`, `multi` / `exec`, `disconnect!` (alias of `close`)
|
|
249
|
+
|
|
250
|
+
Not every redis-rb API is implemented yet. See the [command implementation wiki](https://github.com/valkey-io/valkey-glide-ruby/wiki/The-implementation-status-of-the-Valkey-commands) for coverage.
|
|
251
|
+
|
|
252
|
+
## Building and Testing
|
|
253
|
+
|
|
254
|
+
Instructions for building from source, updating the FFI library, running tests, and contributing are in [DEVELOPER.md](./DEVELOPER.md).
|
|
255
|
+
|
|
256
|
+
For AI-assisted development, see [AGENTS.md](./AGENTS.md) and [CLAUDE.md](./CLAUDE.md).
|
|
257
|
+
|
|
258
|
+
Contributing: [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
259
|
+
|
|
260
|
+
## Community and Feedback
|
|
261
|
+
|
|
262
|
+
We encourage you to join our community to support, share feedback, and ask questions on Valkey Slack: [Join Valkey Slack](https://join.slack.com/t/valkey-oss-developer/shared_invite/zt-2nxs51chx-EB9hu9Qdch3GMfRcztTSkQ).
|
|
263
|
+
|
|
264
|
+
Report issues: [valkey-glide-ruby issues](https://github.com/valkey-io/valkey-glide-ruby/issues).
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
Apache-2.0 — see [LICENSE](https://github.com/valkey-io/valkey-glide-ruby/blob/main/LICENSE) in the repository.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Only load bundler gem tasks when not testing installed gem
|
|
4
|
+
# bundler/gem_tasks can interfere with load path when testing installed gems
|
|
5
|
+
require 'bundler/gem_tasks' unless ENV["TEST_INSTALLED_GEM"]
|
|
6
|
+
require 'rake/testtask'
|
|
7
|
+
|
|
8
|
+
# =============================================================================
|
|
9
|
+
# Native Library Build Tasks
|
|
10
|
+
# =============================================================================
|
|
11
|
+
|
|
12
|
+
def native_lib_ext
|
|
13
|
+
case RbConfig::CONFIG['host_os']
|
|
14
|
+
when /darwin/
|
|
15
|
+
'dylib'
|
|
16
|
+
else
|
|
17
|
+
'so'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
namespace :native do
|
|
22
|
+
desc "Initialize the valkey-glide submodule"
|
|
23
|
+
task :submodule do
|
|
24
|
+
puts "Initializing valkey-glide submodule..."
|
|
25
|
+
sh "git submodule update --init --recursive"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "Build the native FFI library (release mode)"
|
|
29
|
+
task build: :submodule do
|
|
30
|
+
puts "Building native FFI library..."
|
|
31
|
+
Dir.chdir("valkey-glide/ffi") do
|
|
32
|
+
sh "cargo build --release"
|
|
33
|
+
end
|
|
34
|
+
puts "Native library built successfully!"
|
|
35
|
+
puts "Location: valkey-glide/ffi/target/release/libglide_ffi.#{native_lib_ext}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc "Build the native FFI library (debug mode)"
|
|
39
|
+
task build_debug: :submodule do
|
|
40
|
+
puts "Building native FFI library (debug)..."
|
|
41
|
+
Dir.chdir("valkey-glide/ffi") do
|
|
42
|
+
sh "cargo build"
|
|
43
|
+
end
|
|
44
|
+
puts "Native library built successfully!"
|
|
45
|
+
puts "Location: valkey-glide/ffi/target/debug/libglide_ffi.#{native_lib_ext}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
desc "Clean native build artifacts"
|
|
49
|
+
task :clean do
|
|
50
|
+
puts "Cleaning native build artifacts..."
|
|
51
|
+
if Dir.exist?("valkey-glide/ffi")
|
|
52
|
+
Dir.chdir("valkey-glide/ffi") do
|
|
53
|
+
sh "cargo clean"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
puts "Clean complete!"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
desc "Copy built library to lib/valkey/native/{platform}/ for gem packaging"
|
|
60
|
+
task package: :build do
|
|
61
|
+
require 'fileutils'
|
|
62
|
+
require 'rbconfig'
|
|
63
|
+
|
|
64
|
+
# Determine platform directory name (matches Rust target triple)
|
|
65
|
+
os = case RbConfig::CONFIG['host_os']
|
|
66
|
+
when /darwin/
|
|
67
|
+
'apple-darwin'
|
|
68
|
+
when /linux/
|
|
69
|
+
'unknown-linux-gnu'
|
|
70
|
+
when /mswin|mingw/
|
|
71
|
+
'pc-windows-msvc'
|
|
72
|
+
else
|
|
73
|
+
abort "Unsupported OS: #{RbConfig::CONFIG['host_os']}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
arch = case RbConfig::CONFIG['host_cpu']
|
|
77
|
+
when /x86_64|amd64/i
|
|
78
|
+
'x86_64'
|
|
79
|
+
when /aarch64|arm64/i
|
|
80
|
+
'aarch64'
|
|
81
|
+
else
|
|
82
|
+
abort "Unsupported architecture: #{RbConfig::CONFIG['host_cpu']}"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
platform_dir = "#{arch}-#{os}"
|
|
86
|
+
src = "valkey-glide/ffi/target/release/libglide_ffi.#{native_lib_ext}"
|
|
87
|
+
dest_dir = "lib/valkey/native/#{platform_dir}"
|
|
88
|
+
dest = "#{dest_dir}/libglide_ffi.#{native_lib_ext}"
|
|
89
|
+
|
|
90
|
+
if File.exist?(src)
|
|
91
|
+
FileUtils.mkdir_p(dest_dir)
|
|
92
|
+
FileUtils.cp(src, dest)
|
|
93
|
+
puts "Copied #{src} to #{dest}"
|
|
94
|
+
puts "Platform: #{platform_dir}"
|
|
95
|
+
else
|
|
96
|
+
abort "Native library not found at #{src}. Run 'rake native:build' first."
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
desc "Build the native FFI library"
|
|
102
|
+
task native: "native:build"
|
|
103
|
+
|
|
104
|
+
# =============================================================================
|
|
105
|
+
# Test Tasks
|
|
106
|
+
# =============================================================================
|
|
107
|
+
|
|
108
|
+
namespace :test do
|
|
109
|
+
groups = %i[valkey cluster]
|
|
110
|
+
groups.each do |group|
|
|
111
|
+
Rake::TestTask.new(group) do |t|
|
|
112
|
+
t.libs << "test"
|
|
113
|
+
# Only add local lib to load path when not testing installed gem
|
|
114
|
+
t.libs << "lib" unless ENV["TEST_INSTALLED_GEM"]
|
|
115
|
+
t.test_files = FileList["test/#{group}/**/*_test.rb"]
|
|
116
|
+
t.options = '-v' if ENV['CI'] || ENV['VERBOSE']
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
lost_tests = Dir["test/**/*_test.rb"] - groups.map { |g| Dir["test/#{g}/**/*_test.rb"] }.flatten
|
|
121
|
+
abort "The following test files are in no group:\n#{lost_tests.join("\n")}" unless lost_tests.empty?
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
task test: ["test:valkey"]
|
|
125
|
+
|
|
126
|
+
task default: :test
|
data/examples/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
Runnable examples for Valkey GLIDE Ruby. Requires a Valkey or Redis OSS server unless noted.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
From the repository root:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bin/setup
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Run examples with the gem loaded from `lib/`:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bundle exec ruby examples/standalone.rb
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
RUBYOPT="-I$(pwd)/lib" ruby examples/standalone.rb
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
| File | Description | Server |
|
|
28
|
+
|------|-------------|--------|
|
|
29
|
+
| [standalone.rb](./standalone.rb) | Basic connect, SET, GET | Standalone `:6379` |
|
|
30
|
+
| [cluster.rb](./cluster.rb) | Cluster connect, SET, GET | Cluster `:7000`–`:7005` |
|
|
31
|
+
| [pipelining.rb](./pipelining.rb) | Non-atomic pipeline | Standalone `:6379` |
|
|
32
|
+
| [opentelemetry.rb](./opentelemetry.rb) | OTel file exporter + traced commands | Standalone `:6379` |
|
|
33
|
+
| [statistics.rb](./statistics.rb) | Client statistics | Standalone `:6379` |
|
|
34
|
+
|
|
35
|
+
## Environment variables
|
|
36
|
+
|
|
37
|
+
| Variable | Default | Purpose |
|
|
38
|
+
|----------|---------|---------|
|
|
39
|
+
| `VALKEY_HOST` | `127.0.0.1` | Server host |
|
|
40
|
+
| `VALKEY_PORT` | `6379` | Standalone port |
|
|
41
|
+
| `VALKEY_CLUSTER_PORT` | `7000` | First cluster node port |
|
|
42
|
+
|
|
43
|
+
## Standalone with Docker
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
docker run -d --name valkey -p 6379:6379 valkey/valkey:8
|
|
47
|
+
bundle exec ruby examples/standalone.rb
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Cluster with Docker
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
docker run -d -p 7000-7005:7000-7005 grokzen/redis-cluster:7.0.15
|
|
54
|
+
bundle exec ruby examples/cluster.rb
|
|
55
|
+
```
|
data/examples/cluster.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Cluster mode example.
|
|
4
|
+
#
|
|
5
|
+
# Run: bundle exec ruby examples/cluster.rb
|
|
6
|
+
# Requires a 6-node cluster on 127.0.0.1:7000-7005 (see examples/README.md).
|
|
7
|
+
|
|
8
|
+
require "valkey"
|
|
9
|
+
|
|
10
|
+
base_port = Integer(ENV.fetch("VALKEY_CLUSTER_PORT", 7000))
|
|
11
|
+
host = ENV.fetch("VALKEY_HOST", "127.0.0.1")
|
|
12
|
+
|
|
13
|
+
nodes = 6.times.map { |i| { host: host, port: base_port + i } }
|
|
14
|
+
|
|
15
|
+
client = Valkey.new(nodes: nodes, cluster_mode: true)
|
|
16
|
+
|
|
17
|
+
puts "PING: #{client.ping}"
|
|
18
|
+
puts "SET: #{client.set('cluster_key', 'cluster_value')}"
|
|
19
|
+
puts "GET: #{client.get('cluster_key')}"
|
|
20
|
+
|
|
21
|
+
client.del("cluster_key")
|
|
22
|
+
client.close
|
|
23
|
+
|
|
24
|
+
puts "Done."
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# OpenTelemetry example using file exporters (no collector required).
|
|
4
|
+
#
|
|
5
|
+
# Run: bundle exec ruby examples/opentelemetry.rb
|
|
6
|
+
# Traces: /tmp/valkey_ruby_example_traces.json
|
|
7
|
+
# Metrics: /tmp/valkey_ruby_example_metrics.json
|
|
8
|
+
|
|
9
|
+
require "valkey"
|
|
10
|
+
require "fileutils"
|
|
11
|
+
|
|
12
|
+
TRACES_FILE = "/tmp/valkey_ruby_example_traces.json"
|
|
13
|
+
METRICS_FILE = "/tmp/valkey_ruby_example_metrics.json"
|
|
14
|
+
|
|
15
|
+
FileUtils.rm_f(TRACES_FILE)
|
|
16
|
+
FileUtils.rm_f(METRICS_FILE)
|
|
17
|
+
|
|
18
|
+
Valkey::OpenTelemetry.init(
|
|
19
|
+
traces: {
|
|
20
|
+
endpoint: "file://#{TRACES_FILE}",
|
|
21
|
+
sample_percentage: 100
|
|
22
|
+
},
|
|
23
|
+
metrics: {
|
|
24
|
+
endpoint: "file://#{METRICS_FILE}"
|
|
25
|
+
},
|
|
26
|
+
flush_interval_ms: 1000
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
host = ENV.fetch("VALKEY_HOST", "127.0.0.1")
|
|
30
|
+
port = Integer(ENV.fetch("VALKEY_PORT", 6379))
|
|
31
|
+
|
|
32
|
+
client = Valkey.new(host: host, port: port)
|
|
33
|
+
|
|
34
|
+
client.set("otel_key", "otel_value")
|
|
35
|
+
client.get("otel_key")
|
|
36
|
+
client.pipelined do |pipe|
|
|
37
|
+
pipe.set("otel_pipe_1", "a")
|
|
38
|
+
pipe.get("otel_pipe_1")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
client.del("otel_key", "otel_pipe_1")
|
|
42
|
+
client.close
|
|
43
|
+
|
|
44
|
+
# Allow exporter flush
|
|
45
|
+
sleep 2
|
|
46
|
+
|
|
47
|
+
puts "OpenTelemetry initialized: #{Valkey::OpenTelemetry.initialized?}"
|
|
48
|
+
puts "Traces file: #{TRACES_FILE} (#{File.size?(TRACES_FILE) || 0} bytes)"
|
|
49
|
+
puts "Metrics file: #{METRICS_FILE} (#{File.size?(METRICS_FILE) || 0} bytes)"
|
|
50
|
+
puts "Done."
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Pipeline example — batch commands in one round trip.
|
|
4
|
+
#
|
|
5
|
+
# Run: bundle exec ruby examples/pipelining.rb
|
|
6
|
+
|
|
7
|
+
require "valkey"
|
|
8
|
+
|
|
9
|
+
host = ENV.fetch("VALKEY_HOST", "127.0.0.1")
|
|
10
|
+
port = Integer(ENV.fetch("VALKEY_PORT", 6379))
|
|
11
|
+
|
|
12
|
+
client = Valkey.new(host: host, port: port)
|
|
13
|
+
|
|
14
|
+
client.del("pipe_counter")
|
|
15
|
+
|
|
16
|
+
results = client.pipelined do |pipe|
|
|
17
|
+
pipe.set("pipe_key", "pipe_value")
|
|
18
|
+
pipe.get("pipe_key")
|
|
19
|
+
pipe.incr("pipe_counter")
|
|
20
|
+
pipe.get("pipe_counter")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
puts "Pipeline results:"
|
|
24
|
+
results.each_with_index { |r, i| puts " [#{i}] #{r.inspect}" }
|
|
25
|
+
|
|
26
|
+
client.del("pipe_key", "pipe_counter")
|
|
27
|
+
client.close
|
|
28
|
+
|
|
29
|
+
puts "Done."
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Basic standalone Valkey example.
|
|
4
|
+
#
|
|
5
|
+
# Run: bundle exec ruby examples/standalone.rb
|
|
6
|
+
# Requires Valkey/Redis on VALKEY_HOST:VALKEY_PORT (default 127.0.0.1:6379).
|
|
7
|
+
|
|
8
|
+
require "valkey"
|
|
9
|
+
|
|
10
|
+
host = ENV.fetch("VALKEY_HOST", "127.0.0.1")
|
|
11
|
+
port = Integer(ENV.fetch("VALKEY_PORT", 6379))
|
|
12
|
+
|
|
13
|
+
client = Valkey.new(host: host, port: port)
|
|
14
|
+
|
|
15
|
+
puts "PING: #{client.ping}"
|
|
16
|
+
puts "SET: #{client.set('hello', 'world')}"
|
|
17
|
+
puts "GET: #{client.get('hello')}"
|
|
18
|
+
|
|
19
|
+
client.del("hello")
|
|
20
|
+
client.close
|
|
21
|
+
|
|
22
|
+
puts "Done."
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Client statistics example.
|
|
4
|
+
#
|
|
5
|
+
# Run: bundle exec ruby examples/statistics.rb
|
|
6
|
+
|
|
7
|
+
require "valkey"
|
|
8
|
+
|
|
9
|
+
host = ENV.fetch("VALKEY_HOST", "127.0.0.1")
|
|
10
|
+
port = Integer(ENV.fetch("VALKEY_PORT", 6379))
|
|
11
|
+
|
|
12
|
+
client = Valkey.new(host: host, port: port)
|
|
13
|
+
client.set("stats_demo", "1")
|
|
14
|
+
client.get("stats_demo")
|
|
15
|
+
|
|
16
|
+
stats = client.get_statistics
|
|
17
|
+
|
|
18
|
+
puts "Client statistics:"
|
|
19
|
+
stats.each { |k, v| puts " #{k}: #{v}" }
|
|
20
|
+
|
|
21
|
+
client.del("stats_demo")
|
|
22
|
+
client.close
|
|
23
|
+
|
|
24
|
+
puts "Done."
|