valkey-glide-rb 0.9.2 → 1.0.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 +4 -4
- data/lib/valkey/commands/scripting_commands.rb +2 -20
- data/lib/valkey/commands/string_commands.rb +1 -8
- data/lib/valkey/commands/transaction_commands.rb +14 -65
- data/lib/valkey/native/aarch64-apple-darwin/libglide_ffi.dylib +0 -0
- data/lib/valkey/native/aarch64-unknown-linux-gnu/libglide_ffi.so +0 -0
- data/lib/valkey/native/aarch64-unknown-linux-musl/libglide_ffi.so +0 -0
- data/lib/valkey/native/x86_64-unknown-linux-gnu/libglide_ffi.so +0 -0
- data/lib/valkey/native/x86_64-unknown-linux-musl/libglide_ffi.so +0 -0
- data/lib/valkey/version.rb +1 -1
- data/lib/valkey.rb +18 -29
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 31e06a1cd3c0ecb6cd124d2d65c232cd080f5d5b9c3beaec4edac11ca8c9ddd4
|
|
4
|
+
data.tar.gz: a72a457f3533a2ee91c3b4d3a33633d4a5b19f73482c71fd6405c7c5229b3a1e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3f3384dfc9de4a87b7efd6464e2b724534339e2b56f748f4399283a290303ab54361f057c8069c19bb38ce29f621aa0056ac2f96975f81717c023bdf3a2c75fe
|
|
7
|
+
data.tar.gz: bb8378c230ffde26c7abe0f3755d002c5f2bd67e345b2e380036fd07b5b9731b61c7c61bf36d2302a559d33f769daaa86386986de0f69285839a5638235a7f75
|
|
@@ -137,22 +137,13 @@ class Valkey
|
|
|
137
137
|
# @example Execute script that returns different data types
|
|
138
138
|
# valkey.eval("return {1, 'hello', true, nil}")
|
|
139
139
|
# # => [1, "hello", true, nil]
|
|
140
|
-
# @example Positional form, matching redis-rb's eval(script, keys, argv)
|
|
141
|
-
# valkey.eval("return KEYS[1] .. ARGV[1]", ["mykey"], ["myarg"])
|
|
142
|
-
# # => "mykeynyarg"
|
|
143
140
|
# Since the eval is not available in the rust backend
|
|
144
141
|
# using the load and invoke script
|
|
145
|
-
def eval(script,
|
|
142
|
+
def eval(script, keys: [], args: [])
|
|
146
143
|
# Validate script parameter
|
|
147
144
|
raise ArgumentError, "script must be a string" unless script.is_a?(String)
|
|
148
145
|
raise ArgumentError, "script cannot be empty" if script.empty?
|
|
149
146
|
|
|
150
|
-
# Accept redis-rb's flexible positional form - eval(script, keys, argv)
|
|
151
|
-
# - in addition to the keyword form, mirroring the same treatment
|
|
152
|
-
# applied to evalsha (see that method for the full rationale).
|
|
153
|
-
keys ||= rest[0] || []
|
|
154
|
-
args ||= rest[1] || []
|
|
155
|
-
|
|
156
147
|
# Validate and convert keys and args to strings
|
|
157
148
|
begin
|
|
158
149
|
keys = Array(keys).map(&:to_s)
|
|
@@ -190,22 +181,13 @@ class Valkey
|
|
|
190
181
|
# rescue Valkey::CommandError => e
|
|
191
182
|
# puts "Script not found: #{e.message}"
|
|
192
183
|
# end
|
|
193
|
-
# @example Positional form, matching redis-rb's evalsha(sha, keys, argv)
|
|
194
|
-
# valkey.evalsha(sha, ["user"], ["123"])
|
|
195
|
-
# # => "user:123"
|
|
196
184
|
# Since evalsha is not available in rust backend
|
|
197
185
|
# using invoke script
|
|
198
|
-
def evalsha(sha,
|
|
186
|
+
def evalsha(sha, keys: [], args: [])
|
|
199
187
|
# Validate SHA1 hash parameter
|
|
200
188
|
raise ArgumentError, "sha1 hash must be a string" unless sha.is_a?(String)
|
|
201
189
|
raise ArgumentError, "sha1 hash must be a 40-character hexadecimal string" unless valid_sha1?(sha)
|
|
202
190
|
|
|
203
|
-
# Accept redis-rb's flexible positional form - evalsha(sha, keys, argv)
|
|
204
|
-
# - in addition to the keyword form, so code written against redis-rb's
|
|
205
|
-
# API (e.g. redis_display_id) doesn't need to special-case this client.
|
|
206
|
-
keys ||= rest[0] || []
|
|
207
|
-
args ||= rest[1] || []
|
|
208
|
-
|
|
209
191
|
# Validate and convert keys and args to strings
|
|
210
192
|
begin
|
|
211
193
|
keys = Array(keys).map(&:to_s)
|
|
@@ -129,14 +129,7 @@ class Valkey
|
|
|
129
129
|
# @param [String] value
|
|
130
130
|
# @return [Boolean] whether the key was set or not
|
|
131
131
|
def setnx(key, value)
|
|
132
|
-
|
|
133
|
-
# deliberately used here: glide-core's per-command coercion is keyed by
|
|
134
|
-
# command name alone, so it can't distinguish this dedicated SETNX
|
|
135
|
-
# RequestType from a raw `customCommand(["SETNX", ...])` call, which
|
|
136
|
-
# other GLIDE bindings' existing contracts expect to keep returning a
|
|
137
|
-
# plain 0/1 integer. Doing the conversion here keeps it scoped to this
|
|
138
|
-
# one Ruby-level method - see hexists/hsetnx for the same pattern.
|
|
139
|
-
send_command(RequestType::SET_NX, [key, value], &Utils::Boolify)
|
|
132
|
+
send_command(RequestType::SET_NX, [key, value])
|
|
140
133
|
end
|
|
141
134
|
|
|
142
135
|
# Set one or more values.
|
|
@@ -16,12 +16,8 @@ class Valkey
|
|
|
16
16
|
# end # => ["OK", 6]
|
|
17
17
|
#
|
|
18
18
|
# @yield [multi] the commands that are called inside this block are cached
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# MULTI/EXEC transaction internally. If the block raises, nothing has been
|
|
22
|
-
# sent to the server yet, so the exception simply propagates - there is no
|
|
23
|
-
# transaction to discard.
|
|
24
|
-
# @yieldparam [Valkey::Pipeline] multi collects the block's commands
|
|
19
|
+
# and written to the server upon returning from it
|
|
20
|
+
# @yieldparam [Valkey] multi `self`
|
|
25
21
|
#
|
|
26
22
|
# @return [Array<...>]
|
|
27
23
|
# - an array with replies
|
|
@@ -30,12 +26,17 @@ class Valkey
|
|
|
30
26
|
# @see #unwatch
|
|
31
27
|
def multi
|
|
32
28
|
if block_given?
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
begin
|
|
30
|
+
@in_multi_block = true
|
|
31
|
+
start_multi
|
|
32
|
+
yield(self)
|
|
33
|
+
exec
|
|
34
|
+
rescue StandardError
|
|
35
|
+
discard
|
|
36
|
+
raise
|
|
37
|
+
ensure
|
|
38
|
+
@in_multi_block = false
|
|
39
|
+
end
|
|
39
40
|
else
|
|
40
41
|
start_multi
|
|
41
42
|
self
|
|
@@ -113,12 +114,11 @@ class Valkey
|
|
|
113
114
|
# @see #discard
|
|
114
115
|
def exec
|
|
115
116
|
if @in_multi
|
|
116
|
-
queued_commands = @queued_commands
|
|
117
117
|
begin
|
|
118
118
|
begin
|
|
119
119
|
result = send_command(RequestType::EXEC)
|
|
120
120
|
# If EXEC returns an error object (from array), it's already handled
|
|
121
|
-
result
|
|
121
|
+
result
|
|
122
122
|
rescue CommandError => e
|
|
123
123
|
# If EXEC itself raises an error (like when transaction is aborted),
|
|
124
124
|
# return an array with the error to match expected behavior in tests
|
|
@@ -157,59 +157,8 @@ class Valkey
|
|
|
157
157
|
@queued_commands = []
|
|
158
158
|
end
|
|
159
159
|
|
|
160
|
-
# Commands whose reply is boolean when run standalone (via native return-type
|
|
161
|
-
# coercion server-side), but arrives as a raw 0/1 integer inside an EXEC array,
|
|
162
|
-
# since that coercion is keyed by the single command actually being run - which,
|
|
163
|
-
# for a queued command, is EXEC itself, not the original command.
|
|
164
|
-
#
|
|
165
|
-
# This list mirrors glide-core's own Boolean-coercion table in
|
|
166
|
-
# `value_conversion.rs::expected_type_for_cmd` (HEXISTS, HSETNX, EXPIRE, EXPIREAT,
|
|
167
|
-
# PEXPIRE, PEXPIREAT, SISMEMBER, PERSIST, SMOVE, PFADD, RENAMENX, MOVE, COPY,
|
|
168
|
-
# MSETNX, XGROUP DESTROY, XGROUP CREATECONSUMER) MINUS the commands whose Ruby
|
|
169
|
-
# method already passes its own explicit conversion block (`hexists`/`hsetnx`
|
|
170
|
-
# use `&Utils::Boolify`; `xgroup_destroy`/`xgroup_createconsumer` use a custom
|
|
171
|
-
# bool->int block). Those are already handled correctly by the `if block`
|
|
172
|
-
# branch below, before this list is even consulted - listing them here too
|
|
173
|
-
# would be redundant, not wrong. Every RequestType below calls `send_command`
|
|
174
|
-
# with NO block at all, so this static list is the only place their boolean-ness
|
|
175
|
-
# is recorded.
|
|
176
|
-
#
|
|
177
|
-
# NOTE: SETNX is deliberately NOT in glide-core's coercion table (and so isn't
|
|
178
|
-
# here as a "no block" entry either) - it's `redis-rb`-style boolean-ness only,
|
|
179
|
-
# not something the server/`glide-core` treats as boolean, since coercion there
|
|
180
|
-
# is keyed by command name alone and can't distinguish this dedicated RequestType
|
|
181
|
-
# from a raw `customCommand(["SETNX", ...])` call, which other bindings' existing
|
|
182
|
-
# contracts expect to keep returning a plain integer. `setnx`'s own Ruby method
|
|
183
|
-
# passes `&Utils::Boolify` directly instead - see string_commands.rb - so it's
|
|
184
|
-
# already covered by the `if block` branch, same as hexists/hsetnx.
|
|
185
|
-
BOOLEAN_REQUEST_TYPES = [
|
|
186
|
-
RequestType::EXPIRE, RequestType::EXPIRE_AT, RequestType::PEXPIRE, RequestType::PEXPIRE_AT,
|
|
187
|
-
RequestType::PERSIST, RequestType::SISMEMBER, RequestType::S_MOVE, RequestType::PFADD,
|
|
188
|
-
RequestType::RENAME_NX, RequestType::MOVE, RequestType::COPY, RequestType::MSET_NX
|
|
189
|
-
].freeze
|
|
190
|
-
|
|
191
160
|
private
|
|
192
161
|
|
|
193
|
-
# Re-applies each queued command's own reply conversion (e.g. `&Utils::Boolify`)
|
|
194
|
-
# to EXEC's raw array, since redis-rb's Future-based design does the equivalent
|
|
195
|
-
# (a Future remembers its conversion and re-applies it once EXEC resolves), but
|
|
196
|
-
# queued commands here go through the plain single-command path with no such
|
|
197
|
-
# memory - see BOOLEAN_REQUEST_TYPES above for the case with no explicit block.
|
|
198
|
-
def reconvert_queued_replies(result, queued_commands)
|
|
199
|
-
return result unless result.size == queued_commands.size
|
|
200
|
-
|
|
201
|
-
result.each_with_index.map do |value, i|
|
|
202
|
-
command_type, _args, block = queued_commands[i]
|
|
203
|
-
if block
|
|
204
|
-
block.call(value)
|
|
205
|
-
elsif BOOLEAN_REQUEST_TYPES.include?(command_type)
|
|
206
|
-
Utils::Boolify.call(value)
|
|
207
|
-
else
|
|
208
|
-
value
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
|
|
213
162
|
# Start a MULTI block if one isn't already active.
|
|
214
163
|
#
|
|
215
164
|
# This mirrors the behaviour of popular Valkey/Redis clients where
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/valkey/version.rb
CHANGED
data/lib/valkey.rb
CHANGED
|
@@ -457,9 +457,7 @@ class Valkey
|
|
|
457
457
|
RequestType::MULTI, RequestType::EXEC, RequestType::DISCARD,
|
|
458
458
|
RequestType::WATCH, RequestType::UNWATCH
|
|
459
459
|
]
|
|
460
|
-
if !tx_commands.include?(command_type) && result == "QUEUED"
|
|
461
|
-
@queued_commands << [command_type, command_args.dup, block]
|
|
462
|
-
end
|
|
460
|
+
@queued_commands << [command_type, command_args.dup] if !tx_commands.include?(command_type) && result == "QUEUED"
|
|
463
461
|
end
|
|
464
462
|
|
|
465
463
|
result
|
|
@@ -467,29 +465,23 @@ class Valkey
|
|
|
467
465
|
|
|
468
466
|
private
|
|
469
467
|
|
|
470
|
-
def send_batch_commands(commands, exception: true
|
|
468
|
+
def send_batch_commands(commands, exception: true)
|
|
471
469
|
# WORKAROUND: The underlying Glide FFI backend has stability issues when
|
|
472
|
-
# batching
|
|
473
|
-
#
|
|
474
|
-
#
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
results
|
|
484
|
-
|
|
485
|
-
commands.each do |command_type, command_args, block|
|
|
486
|
-
res = send_command(command_type, command_args)
|
|
487
|
-
res = block.call(res) if block
|
|
488
|
-
results << res
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
return results
|
|
470
|
+
# batching transactional commands like MULTI / EXEC / DISCARD. To avoid
|
|
471
|
+
# native crashes we fall back to issuing those commands sequentially
|
|
472
|
+
# instead of via `Bindings.batch`.
|
|
473
|
+
tx_types = [RequestType::MULTI, RequestType::EXEC, RequestType::DISCARD]
|
|
474
|
+
|
|
475
|
+
if commands.any? { |(command_type, _args, _block)| tx_types.include?(command_type) }
|
|
476
|
+
results = []
|
|
477
|
+
|
|
478
|
+
commands.each do |command_type, command_args, block|
|
|
479
|
+
res = send_command(command_type, command_args)
|
|
480
|
+
res = block.call(res) if block
|
|
481
|
+
results << res
|
|
492
482
|
end
|
|
483
|
+
|
|
484
|
+
return results
|
|
493
485
|
end
|
|
494
486
|
|
|
495
487
|
cmds = []
|
|
@@ -519,7 +511,7 @@ class Valkey
|
|
|
519
511
|
batch_info = Bindings::BatchInfo.new
|
|
520
512
|
batch_info[:cmd_count] = cmds.size
|
|
521
513
|
batch_info[:cmds] = cmd_ptrs
|
|
522
|
-
batch_info[:is_atomic] =
|
|
514
|
+
batch_info[:is_atomic] = false
|
|
523
515
|
|
|
524
516
|
batch_options = Bindings::BatchOptionsInfo.new
|
|
525
517
|
batch_options[:retry_server_error] = true
|
|
@@ -708,10 +700,7 @@ class Valkey
|
|
|
708
700
|
|
|
709
701
|
response = convert_response.call(result)
|
|
710
702
|
|
|
711
|
-
|
|
712
|
-
# "QUEUED" sentinel - send_command's own `result == "QUEUED"` check (used to
|
|
713
|
-
# track queued commands) needs to see the literal string, not e.g. `true`.
|
|
714
|
-
if block_given? && response != "QUEUED"
|
|
703
|
+
if block_given?
|
|
715
704
|
block.call(response)
|
|
716
705
|
else
|
|
717
706
|
response
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: valkey-glide-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0.pre.rc1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Valkey GLIDE Maintainers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|