valkey-rb 1.0.0
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 +58 -0
- data/.rubocop_todo.yml +22 -0
- data/README.md +95 -0
- data/Rakefile +23 -0
- data/lib/valkey/bindings.rb +224 -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 +587 -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 +286 -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 +359 -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/libglide_ffi.so +0 -0
- data/lib/valkey/opentelemetry.rb +207 -0
- data/lib/valkey/pipeline.rb +20 -0
- data/lib/valkey/protobuf/command_request_pb.rb +51 -0
- data/lib/valkey/protobuf/connection_request_pb.rb +51 -0
- data/lib/valkey/protobuf/response_pb.rb +39 -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 +253 -0
- data/lib/valkey/version.rb +5 -0
- data/lib/valkey.rb +551 -0
- metadata +119 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a20f9cdffea000924afe9304a0c63bae69be3eeaae532f1ae64e7ec562403eb3
|
|
4
|
+
data.tar.gz: e451bc8429e5514e1b76115507c40a26e7698a01f6a1a5aa39c597c3da2f9170
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d8300adf645ac1de3bfb33ca882016e9d943f3ed033e3f0b5d7397478af22e45a52bae7e1aa7ac3b55eb8acf4b25090d3e46cc6bf63ad97f7cb93d65e78c0a15
|
|
7
|
+
data.tar.gz: 55e5127393ca215b079cb6c9622f9640d5aa2fdf9143fe44c86acaf3dce766ecf8c6530cacdaa28983c9e46ae08c8347c4fedc623cc0dba169ff55d0b8a1f43b
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
|
2
|
+
|
|
3
|
+
AllCops:
|
|
4
|
+
TargetRubyVersion: 2.6
|
|
5
|
+
NewCops: enable
|
|
6
|
+
Exclude:
|
|
7
|
+
- 'vendor/**/*'
|
|
8
|
+
- 'lib/valkey/protobuf/**/*.rb'
|
|
9
|
+
|
|
10
|
+
Style/StringLiterals:
|
|
11
|
+
Enabled: false
|
|
12
|
+
|
|
13
|
+
Metrics/ParameterLists:
|
|
14
|
+
Enabled: false
|
|
15
|
+
|
|
16
|
+
Metrics/PerceivedComplexity:
|
|
17
|
+
Enabled: false
|
|
18
|
+
|
|
19
|
+
Style/Documentation:
|
|
20
|
+
Enabled: false
|
|
21
|
+
|
|
22
|
+
Naming/MethodParameterName:
|
|
23
|
+
Enabled: false
|
|
24
|
+
|
|
25
|
+
Naming/AccessorMethodName:
|
|
26
|
+
Enabled: false
|
|
27
|
+
|
|
28
|
+
Lint/DuplicateBranch:
|
|
29
|
+
Enabled: false
|
|
30
|
+
|
|
31
|
+
Metrics/AbcSize:
|
|
32
|
+
Enabled: false
|
|
33
|
+
|
|
34
|
+
Metrics/CyclomaticComplexity:
|
|
35
|
+
Enabled: false
|
|
36
|
+
|
|
37
|
+
Metrics/MethodLength:
|
|
38
|
+
Max: 20
|
|
39
|
+
Exclude:
|
|
40
|
+
- 'lib/valkey.rb'
|
|
41
|
+
- 'lib/valkey/opentelemetry.rb'
|
|
42
|
+
- 'test/**/*.rb'
|
|
43
|
+
|
|
44
|
+
Metrics/ClassLength:
|
|
45
|
+
Exclude:
|
|
46
|
+
- 'lib/valkey.rb'
|
|
47
|
+
- 'test/**/*.rb'
|
|
48
|
+
|
|
49
|
+
Metrics/BlockNesting:
|
|
50
|
+
Exclude:
|
|
51
|
+
- 'test_app/**/*.rb'
|
|
52
|
+
|
|
53
|
+
Metrics/ModuleLength:
|
|
54
|
+
Exclude:
|
|
55
|
+
- 'lib/valkey/request_type.rb'
|
|
56
|
+
- 'lib/valkey/utils.rb'
|
|
57
|
+
- 'lib/valkey/commands/*.rb'
|
|
58
|
+
- 'test/**/*.rb'
|
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2025-07-15 13:27:05 UTC using RuboCop version 1.78.0.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
11
|
+
# AllowedMethods: refine
|
|
12
|
+
Metrics/BlockLength:
|
|
13
|
+
Max: 35
|
|
14
|
+
Exclude:
|
|
15
|
+
- 'lib/valkey.rb'
|
|
16
|
+
|
|
17
|
+
# Offense count: 1
|
|
18
|
+
# Configuration parameters: CountComments, CountAsOne.
|
|
19
|
+
Metrics/ClassLength:
|
|
20
|
+
Max: 111
|
|
21
|
+
Exclude:
|
|
22
|
+
- 'lib/valkey.rb'
|
data/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Valkey
|
|
2
|
+
|
|
3
|
+
A Ruby client library for [Valkey][valkey-home] built with [Valkey Glide Core][valkey-glide-home] that tries to provide a drop in replacement for redis-rb.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **High Performance**: Built on Valkey GLIDE Core (Rust-based) for optimal performance
|
|
8
|
+
- **OpenTelemetry Integration**: Built-in distributed tracing support
|
|
9
|
+
- **Client Statistics**: Real-time monitoring of connections and commands
|
|
10
|
+
- **Drop-in Replacement**: Compatible with redis-rb API
|
|
11
|
+
|
|
12
|
+
## Getting started
|
|
13
|
+
|
|
14
|
+
Install with:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
$ gem install valkey
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
You can connect to Valkey by instantiating the `Valkey` class:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
require "valkey"
|
|
24
|
+
|
|
25
|
+
valkey = Valkey.new
|
|
26
|
+
|
|
27
|
+
valkey.set("mykey", "hello world")
|
|
28
|
+
# => "OK"
|
|
29
|
+
|
|
30
|
+
valkey.get("mykey")
|
|
31
|
+
# => "hello world"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## OpenTelemetry and Monitoring
|
|
35
|
+
|
|
36
|
+
The Valkey client includes built-in support for OpenTelemetry distributed tracing and client statistics monitoring.
|
|
37
|
+
|
|
38
|
+
### OpenTelemetry Tracing
|
|
39
|
+
|
|
40
|
+
Enable automatic tracing of all Valkey operations:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
require 'valkey'
|
|
44
|
+
require 'opentelemetry/sdk'
|
|
45
|
+
|
|
46
|
+
# Configure OpenTelemetry
|
|
47
|
+
OpenTelemetry::SDK.configure do |c|
|
|
48
|
+
c.service_name = 'my-app'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Create client with tracing enabled
|
|
52
|
+
client = Valkey.new(
|
|
53
|
+
host: 'localhost',
|
|
54
|
+
port: 6379,
|
|
55
|
+
tracing: true
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# All commands are automatically traced
|
|
59
|
+
client.set('key', 'value')
|
|
60
|
+
client.get('key')
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Client Statistics
|
|
64
|
+
|
|
65
|
+
Monitor connection and command metrics in real-time:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
client = Valkey.new
|
|
69
|
+
|
|
70
|
+
# Execute some operations
|
|
71
|
+
client.set('key1', 'value1')
|
|
72
|
+
client.get('key1')
|
|
73
|
+
|
|
74
|
+
# Get statistics
|
|
75
|
+
stats = client.get_statistics
|
|
76
|
+
|
|
77
|
+
puts "Active connections: #{stats[:connection_stats][:active_connections]}"
|
|
78
|
+
puts "Total commands: #{stats[:command_stats][:total_commands]}"
|
|
79
|
+
puts "Success rate: #{
|
|
80
|
+
(stats[:command_stats][:successful_commands].to_f /
|
|
81
|
+
stats[:command_stats][:total_commands] * 100).round(2)
|
|
82
|
+
}%"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For detailed documentation, see [OPENTELEMETRY_GUIDE.md](OPENTELEMETRY_GUIDE.md) and [opentelemetry_example.rb](opentelemetry_example.rb).
|
|
86
|
+
|
|
87
|
+
## Documentation
|
|
88
|
+
|
|
89
|
+
Checkout [the implementation status of the Valkey commands][commands-implementation-progress].
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
[valkey-home]: https://valkey.io
|
|
93
|
+
[valkey-glide-home]: https://github.com/valkey-io/valkey-glide
|
|
94
|
+
[commands-implementation-progress]: https://github.com/valkey-io/valkey-glide-ruby/wiki/The-implementation-status-of-the-Valkey-commands
|
|
95
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rake/testtask'
|
|
5
|
+
|
|
6
|
+
namespace :test do
|
|
7
|
+
groups = %i[valkey cluster]
|
|
8
|
+
groups.each do |group|
|
|
9
|
+
Rake::TestTask.new(group) do |t|
|
|
10
|
+
t.libs << "test"
|
|
11
|
+
t.libs << "lib"
|
|
12
|
+
t.test_files = FileList["test/#{group}/**/*_test.rb"]
|
|
13
|
+
t.options = '-v' if ENV['CI'] || ENV['VERBOSE']
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
lost_tests = Dir["test/**/*_test.rb"] - groups.map { |g| Dir["test/#{g}/**/*_test.rb"] }.flatten
|
|
18
|
+
abort "The following test files are in no group:\n#{lost_tests.join("\n")}" unless lost_tests.empty?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
task test: ["test:valkey"]
|
|
22
|
+
|
|
23
|
+
task default: :test
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Valkey
|
|
4
|
+
module Bindings
|
|
5
|
+
extend FFI::Library
|
|
6
|
+
|
|
7
|
+
lib_ext = FFI::Platform.mac? ? "dylib" : "so"
|
|
8
|
+
ffi_lib File.expand_path("./libglide_ffi.#{lib_ext}", __dir__)
|
|
9
|
+
|
|
10
|
+
class ClientType < FFI::Struct
|
|
11
|
+
layout(
|
|
12
|
+
:tag, :uint # 0 = AsyncClient, 1 = SyncClient
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class ConnectionResponse < FFI::Struct
|
|
17
|
+
layout(
|
|
18
|
+
:conn_ptr, :pointer, # *const c_void
|
|
19
|
+
:connection_error_message, :string # *const c_char (null-terminated C string)
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class CommandError < FFI::Struct
|
|
24
|
+
layout(
|
|
25
|
+
:command_error_message, :string,
|
|
26
|
+
:command_error_type, :int # Assuming RequestErrorType is repr(C) enum
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class BatchOptionsInfo < FFI::Struct
|
|
31
|
+
layout(
|
|
32
|
+
:retry_server_error, :bool,
|
|
33
|
+
:retry_connection_error, :bool,
|
|
34
|
+
:has_timeout, :bool,
|
|
35
|
+
:timeout, :uint, # Assuming u32 is represented as uint in C
|
|
36
|
+
:route_info, :pointer # *const RouteInfo
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class CmdInfo < FFI::Struct
|
|
41
|
+
layout(
|
|
42
|
+
:request_type, :int, # Assuming RequestType is repr(C) enum
|
|
43
|
+
:args, :pointer, # *const *const u8 (pointer to array of pointers to args)
|
|
44
|
+
:arg_count, :ulong, # usize (number of arguments)
|
|
45
|
+
:args_len, :pointer # *const usize (pointer to array of argument lengths)
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class ScriptHashBuffer < FFI::Struct
|
|
50
|
+
layout(
|
|
51
|
+
:ptr, :pointer, # *mut u8 (pointer to the script hash)
|
|
52
|
+
:len, :ulong, # usize (length of the script hash)
|
|
53
|
+
:capacity, :ulong # usize (capacity of the buffer)
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class BatchInfo < FFI::Struct
|
|
58
|
+
layout(
|
|
59
|
+
:cmd_count, :ulong, # usize
|
|
60
|
+
:cmds, :pointer, # *const *const CmdInfo
|
|
61
|
+
:is_atomic, :bool # bool
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class CommandResponse < FFI::Struct
|
|
66
|
+
layout(
|
|
67
|
+
:response_type, :int, # Assuming ResponseType is repr(C) enum
|
|
68
|
+
:int_value, :int64,
|
|
69
|
+
:float_value, :double,
|
|
70
|
+
:bool_value, :bool,
|
|
71
|
+
:string_value, :pointer, # points to C string
|
|
72
|
+
:string_value_len, :long,
|
|
73
|
+
:array_value, :pointer, # points to CommandResponse array
|
|
74
|
+
:array_value_len, :long,
|
|
75
|
+
:map_key, :pointer, # CommandResponse*
|
|
76
|
+
:map_value, :pointer, # CommandResponse*
|
|
77
|
+
:sets_value, :pointer, # CommandResponse*
|
|
78
|
+
:sets_value_len, :long
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
callback :success_callback, %i[ulong pointer], :void
|
|
83
|
+
callback :failure_callback, %i[ulong string int], :void
|
|
84
|
+
|
|
85
|
+
class AsyncClientData < FFI::Struct
|
|
86
|
+
layout(
|
|
87
|
+
:success_callback, :success_callback,
|
|
88
|
+
:failure_callback, :failure_callback
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class ClientData < FFI::Union
|
|
93
|
+
layout(
|
|
94
|
+
:async_client, AsyncClientData
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class CommandResult < FFI::Struct
|
|
99
|
+
layout(
|
|
100
|
+
:response, CommandResponse.by_ref,
|
|
101
|
+
:command_error, CommandError.by_ref
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
callback :pubsub_callback, [
|
|
106
|
+
:ulong, # client_ptr
|
|
107
|
+
:int, # kind (PushKind enum)
|
|
108
|
+
:pointer, :long, # message + length
|
|
109
|
+
:pointer, :long, # channel + length
|
|
110
|
+
:pointer, :long # pattern + length
|
|
111
|
+
], :void
|
|
112
|
+
|
|
113
|
+
attach_function :create_client, [
|
|
114
|
+
:pointer, # *const u8 (connection_request_bytes)
|
|
115
|
+
:ulong, # usize (connection_request_len)
|
|
116
|
+
ClientType.by_ref, # *const ClientType
|
|
117
|
+
:pubsub_callback # callback
|
|
118
|
+
], :pointer # *const ConnectionResponse
|
|
119
|
+
|
|
120
|
+
attach_function :close_client, [
|
|
121
|
+
:pointer # client_adapter_ptr
|
|
122
|
+
], :void
|
|
123
|
+
|
|
124
|
+
attach_function :command, [
|
|
125
|
+
:pointer, # client_adapter_ptr
|
|
126
|
+
:ulong, # request_id
|
|
127
|
+
:int, # command_type
|
|
128
|
+
:ulong, # arg_count
|
|
129
|
+
:pointer, # args (pointer to usize[])
|
|
130
|
+
:pointer, # args_len (pointer to c_ulong[])
|
|
131
|
+
:pointer, # route_bytes
|
|
132
|
+
:ulong, # route_bytes_len
|
|
133
|
+
:ulong # span_ptr (u64)
|
|
134
|
+
], :pointer # returns *mut CommandResult
|
|
135
|
+
|
|
136
|
+
attach_function :batch, [
|
|
137
|
+
:pointer, # client_ptr
|
|
138
|
+
:ulong, # callback_index
|
|
139
|
+
BatchInfo.by_ref, # *const BatchInfo
|
|
140
|
+
:bool, # raise_on_error
|
|
141
|
+
:pointer, # *const BatchOptionsInfo
|
|
142
|
+
:ulong # span_ptr (u64)
|
|
143
|
+
], :pointer # returns *mut CommandResult
|
|
144
|
+
|
|
145
|
+
attach_function :store_script, [
|
|
146
|
+
:pointer, # *const u8 (script_bytes)
|
|
147
|
+
:ulong # usize (script_len)
|
|
148
|
+
], :pointer # returns *mut ScriptHashBuffer
|
|
149
|
+
|
|
150
|
+
attach_function :invoke_script, [
|
|
151
|
+
:pointer, # client_ptr
|
|
152
|
+
:ulong, # request_id
|
|
153
|
+
:pointer, # hash (pointer to C string)
|
|
154
|
+
:ulong, # keys_count (number of keys)
|
|
155
|
+
:pointer, # keys (pointer to usize[])
|
|
156
|
+
:pointer, # keys_len (pointer to c_ulong[])
|
|
157
|
+
:ulong, # args_count (number of args)
|
|
158
|
+
:pointer, # args (pointer to usize[])
|
|
159
|
+
:pointer, # args_len (pointer to c_ulong[])
|
|
160
|
+
:pointer, # route_bytes (pointer to u8)
|
|
161
|
+
:ulong # route_bytes_len (usize)
|
|
162
|
+
], :pointer # returns *mut CommandResult
|
|
163
|
+
|
|
164
|
+
# OpenTelemetry structures
|
|
165
|
+
class OpenTelemetryTracesConfig < FFI::Struct
|
|
166
|
+
layout(
|
|
167
|
+
:endpoint, :pointer, # const char* (trace collector endpoint)
|
|
168
|
+
:has_sample_percentage, :bool, # whether sample_percentage is set
|
|
169
|
+
:sample_percentage, :uint32 # sampling percentage (0-100)
|
|
170
|
+
)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
class OpenTelemetryMetricsConfig < FFI::Struct
|
|
174
|
+
layout(
|
|
175
|
+
:endpoint, :pointer # const char* (metrics collector endpoint)
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
class OpenTelemetryConfig < FFI::Struct
|
|
180
|
+
layout(
|
|
181
|
+
:traces, :pointer, # OpenTelemetryTracesConfig*
|
|
182
|
+
:metrics, :pointer, # OpenTelemetryMetricsConfig*
|
|
183
|
+
:has_flush_interval_ms, :bool, # whether flush_interval_ms is set
|
|
184
|
+
:flush_interval_ms, :int64 # flush interval in milliseconds
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Statistics structure
|
|
189
|
+
class Statistics < FFI::Struct
|
|
190
|
+
layout(
|
|
191
|
+
:total_connections, :ulong, # total connections opened to Valkey
|
|
192
|
+
:total_clients, :ulong, # total GLIDE clients created
|
|
193
|
+
:total_values_compressed, :ulong, # number of values compressed
|
|
194
|
+
:total_values_decompressed, :ulong, # number of values decompressed
|
|
195
|
+
:total_original_bytes, :ulong, # bytes before compression
|
|
196
|
+
:total_bytes_compressed, :ulong, # bytes after compression
|
|
197
|
+
:total_bytes_decompressed, :ulong, # bytes after decompression
|
|
198
|
+
:compression_skipped_count, :ulong # times compression was skipped
|
|
199
|
+
)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# OpenTelemetry functions
|
|
203
|
+
attach_function :init_open_telemetry, [
|
|
204
|
+
OpenTelemetryConfig.by_ref # OpenTelemetry configuration
|
|
205
|
+
], :pointer # returns error string or NULL on success
|
|
206
|
+
|
|
207
|
+
attach_function :free_c_string, [
|
|
208
|
+
:pointer # C string to free
|
|
209
|
+
], :void
|
|
210
|
+
|
|
211
|
+
attach_function :create_otel_span, [
|
|
212
|
+
:int # request_type (RequestType enum value)
|
|
213
|
+
], :uint64 # returns span pointer (u64) or 0 on failure
|
|
214
|
+
|
|
215
|
+
attach_function :create_batch_otel_span, [], :uint64 # returns span pointer (u64) or 0 on failure
|
|
216
|
+
|
|
217
|
+
attach_function :drop_otel_span, [
|
|
218
|
+
:uint64 # span_ptr to close
|
|
219
|
+
], :void
|
|
220
|
+
|
|
221
|
+
# Statistics function
|
|
222
|
+
attach_function :get_statistics, [], Statistics.by_value # returns statistics by value
|
|
223
|
+
end
|
|
224
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Valkey
|
|
4
|
+
module Commands
|
|
5
|
+
# this module contains commands related to BITMAP data type.
|
|
6
|
+
#
|
|
7
|
+
# @see https://valkey.io/commands/#bitmap
|
|
8
|
+
#
|
|
9
|
+
module BitmapCommands
|
|
10
|
+
# Sets or clears the bit at offset in the string value stored at key.
|
|
11
|
+
#
|
|
12
|
+
# @param [String] key
|
|
13
|
+
# @param [Integer] offset bit offset
|
|
14
|
+
# @param [Integer] value bit value `0` or `1`
|
|
15
|
+
# @return [Integer] the original bit value stored at `offset`
|
|
16
|
+
def setbit(key, offset, value)
|
|
17
|
+
send_command(RequestType::SET_BIT, [key, offset, value])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the bit value at offset in the string value stored at key.
|
|
21
|
+
#
|
|
22
|
+
# @param [String] key
|
|
23
|
+
# @param [Integer] offset bit offset
|
|
24
|
+
# @return [Integer] `0` or `1`
|
|
25
|
+
def getbit(key, offset)
|
|
26
|
+
send_command(RequestType::GET_BIT, [key, offset])
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Count the number of set bits in a range of the string value stored at key.
|
|
30
|
+
#
|
|
31
|
+
# @param [String] key
|
|
32
|
+
# @param [Integer] start start index
|
|
33
|
+
# @param [Integer] stop stop index
|
|
34
|
+
# @param [String, Symbol] scale the scale of the offset range
|
|
35
|
+
# e.g. 'BYTE' - interpreted as a range of bytes, 'BIT' - interpreted as a range of bits
|
|
36
|
+
# @return [Integer] the number of bits set to 1
|
|
37
|
+
def bitcount(key, start = 0, stop = -1, scale: nil)
|
|
38
|
+
args = [key, start, stop]
|
|
39
|
+
args << scale if scale
|
|
40
|
+
send_command(RequestType::BIT_COUNT, args)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Perform a bitwise operation between strings and store the resulting string in a key.
|
|
44
|
+
#
|
|
45
|
+
# @param [String] operation e.g. `and`, `or`, `xor`, `not`
|
|
46
|
+
# @param [String] destkey destination key
|
|
47
|
+
# @param [String, Array<String>] keys one or more source keys to perform `operation`
|
|
48
|
+
# @return [Integer] the length of the string stored in `destkey`
|
|
49
|
+
def bitop(operation, destkey, *keys)
|
|
50
|
+
keys.flatten!(1)
|
|
51
|
+
args = [operation, destkey]
|
|
52
|
+
args.concat(keys)
|
|
53
|
+
|
|
54
|
+
send_command(RequestType::BIT_OP, args)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def bitfield(key, *args)
|
|
58
|
+
send_command(RequestType::BIT_FIELD, [key] + args.map(&:to_s))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def bitfield_ro(key, *args)
|
|
62
|
+
send_command(RequestType::BIT_FIELD_READ_ONLY, [key] + args.map(&:to_s))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Return the position of the first bit set to 1 or 0 in a string.
|
|
66
|
+
#
|
|
67
|
+
# @param [String] key
|
|
68
|
+
# @param [Integer] bit whether to look for the first 1 or 0 bit
|
|
69
|
+
# @param [Integer] start start index
|
|
70
|
+
# @param [Integer] stop stop index
|
|
71
|
+
# @param [String, Symbol] scale the scale of the offset range
|
|
72
|
+
# e.g. 'BYTE' - interpreted as a range of bytes, 'BIT' - interpreted as a range of bits
|
|
73
|
+
# @return [Integer] the position of the first 1/0 bit.
|
|
74
|
+
# -1 if looking for 1 and it is not found or start and stop are given.
|
|
75
|
+
def bitpos(key, bit, start = nil, stop = nil, scale: nil)
|
|
76
|
+
raise(ArgumentError, 'stop parameter specified without start parameter') if stop && !start
|
|
77
|
+
|
|
78
|
+
args = [key, bit]
|
|
79
|
+
args << start if start
|
|
80
|
+
args << stop if stop
|
|
81
|
+
args << scale if scale
|
|
82
|
+
send_command(RequestType::BIT_POS, args)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|