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
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Valkey
|
|
4
|
+
module Commands
|
|
5
|
+
# This module contains commands on the Hash data type.
|
|
6
|
+
#
|
|
7
|
+
# @see https://valkey.io/commands/#hash
|
|
8
|
+
#
|
|
9
|
+
module HashCommands
|
|
10
|
+
# Delete one or more hash fields.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# valkey.hdel("hash", "field1", "field2")
|
|
14
|
+
# # => 2
|
|
15
|
+
#
|
|
16
|
+
# @param [String] key
|
|
17
|
+
# @param [String, Array<String>] field one field, or array of fields
|
|
18
|
+
# @return [Integer] the number of fields that were removed
|
|
19
|
+
def hdel(key, *fields)
|
|
20
|
+
fields.flatten!(1)
|
|
21
|
+
send_command(RequestType::HDEL, [key].concat(fields))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Determine if a hash field exists.
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# valkey.hexists("hash", "field")
|
|
28
|
+
# # => true
|
|
29
|
+
#
|
|
30
|
+
# @param [String] key
|
|
31
|
+
# @param [String] field
|
|
32
|
+
# @return [Boolean] whether the field exists
|
|
33
|
+
def hexists(key, field)
|
|
34
|
+
send_command(RequestType::HEXISTS, [key, field], &Utils::Boolify)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Get the value of a hash field.
|
|
38
|
+
#
|
|
39
|
+
# @example
|
|
40
|
+
# valkey.hget("hash", "field")
|
|
41
|
+
# # => "value"
|
|
42
|
+
#
|
|
43
|
+
# @param [String] key
|
|
44
|
+
# @param [String] field
|
|
45
|
+
# @return [String, nil] the value of the field, or nil if the field does not exist
|
|
46
|
+
def hget(key, field)
|
|
47
|
+
send_command(RequestType::HGET, [key, field])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Get all the fields and values in a hash.
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# valkey.hgetall("hash")
|
|
54
|
+
# # => {"field1" => "value1", "field2" => "value2"}
|
|
55
|
+
#
|
|
56
|
+
# @param [String] key
|
|
57
|
+
# @return [Hash] a hash mapping fields to their values
|
|
58
|
+
def hgetall(key)
|
|
59
|
+
send_command(RequestType::HGET_ALL, [key], &Utils::Hashify)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Increment the integer value of a hash field by the given number.
|
|
63
|
+
#
|
|
64
|
+
# @example
|
|
65
|
+
# valkey.hincrby("hash", "field", 5)
|
|
66
|
+
# # => 10
|
|
67
|
+
#
|
|
68
|
+
# @param [String] key
|
|
69
|
+
# @param [String] field
|
|
70
|
+
# @param [Integer] increment
|
|
71
|
+
# @return [Integer] value after incrementing it
|
|
72
|
+
def hincrby(key, field, increment)
|
|
73
|
+
send_command(RequestType::HINCR_BY, [key, field, Integer(increment)])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Increment the numeric value of a hash field by the given float number.
|
|
77
|
+
#
|
|
78
|
+
# @example
|
|
79
|
+
# valkey.hincrbyfloat("hash", "field", 1.23)
|
|
80
|
+
# # => 1.23
|
|
81
|
+
#
|
|
82
|
+
# @param [String] key
|
|
83
|
+
# @param [String] field
|
|
84
|
+
# @param [Float] increment
|
|
85
|
+
# @return [Float] value after incrementing it
|
|
86
|
+
def hincrbyfloat(key, field, increment)
|
|
87
|
+
send_command(RequestType::HINCR_BY_FLOAT, [key, field, Float(increment)], &Utils::Floatify)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Get all the fields in a hash.
|
|
91
|
+
#
|
|
92
|
+
# @example
|
|
93
|
+
# valkey.hkeys("hash")
|
|
94
|
+
# # => ["field1", "field2"]
|
|
95
|
+
#
|
|
96
|
+
# @param [String] key
|
|
97
|
+
# @return [Array<String>] an array of field names
|
|
98
|
+
def hkeys(key)
|
|
99
|
+
send_command(RequestType::HKEYS, [key])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Get the number of fields in a hash.
|
|
103
|
+
#
|
|
104
|
+
# @example
|
|
105
|
+
# valkey.hlen("hash")
|
|
106
|
+
# # => 2
|
|
107
|
+
#
|
|
108
|
+
# @param [String] key
|
|
109
|
+
# @return [Integer] the number of fields in the hash
|
|
110
|
+
def hlen(key)
|
|
111
|
+
send_command(RequestType::HLEN, [key])
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Get the values of all the given hash fields.
|
|
115
|
+
#
|
|
116
|
+
# @example
|
|
117
|
+
# valkey.hmget("hash", "field1", "field2")
|
|
118
|
+
# # => ["value1", "value2"]
|
|
119
|
+
#
|
|
120
|
+
# @param [String] key
|
|
121
|
+
# @param [String, Array<String>] field one field, or array of fields
|
|
122
|
+
# @return [Array<String, nil>] an array of values for the specified fields
|
|
123
|
+
#
|
|
124
|
+
# @see #mapped_hmget
|
|
125
|
+
def hmget(key, *fields, &blk)
|
|
126
|
+
fields.flatten!(1)
|
|
127
|
+
send_command(RequestType::HMGET, [key].concat(fields), &blk)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Get the values of all the given hash fields.
|
|
131
|
+
#
|
|
132
|
+
# @example
|
|
133
|
+
# valkey.mapped_hmget("hash", "field1", "field2")
|
|
134
|
+
# # => {"field1" => "value1", "field2" => "value2"}
|
|
135
|
+
#
|
|
136
|
+
# @param [String] key
|
|
137
|
+
# @param [String, Array<String>] field one field, or array of fields
|
|
138
|
+
# @return [Hash] a hash mapping the specified fields to their values
|
|
139
|
+
#
|
|
140
|
+
# @see #hmget
|
|
141
|
+
def mapped_hmget(key, *fields)
|
|
142
|
+
fields.flatten!(1)
|
|
143
|
+
hmget(key, fields) do |reply|
|
|
144
|
+
if reply.is_a?(Array)
|
|
145
|
+
fields.zip(reply).to_h
|
|
146
|
+
else
|
|
147
|
+
reply
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Set multiple hash fields to multiple values.
|
|
153
|
+
#
|
|
154
|
+
# @example
|
|
155
|
+
# valkey.hmset("hash", "field1", "value1", "field2", "value2")
|
|
156
|
+
# # => "OK"
|
|
157
|
+
#
|
|
158
|
+
# @param [String] key
|
|
159
|
+
# @param [Array<String>] args array of field-value pairs
|
|
160
|
+
# @return [String] `"OK"`
|
|
161
|
+
#
|
|
162
|
+
# @see #mapped_hmset
|
|
163
|
+
def hmset(key, *args)
|
|
164
|
+
send_command(RequestType::HMSET, [key].concat(args))
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Set multiple hash fields to multiple values.
|
|
168
|
+
#
|
|
169
|
+
# @example
|
|
170
|
+
# valkey.mapped_hmset("hash", { "field1" => "value1", "field2" => "value2" })
|
|
171
|
+
# # => "OK"
|
|
172
|
+
#
|
|
173
|
+
# @param [String] key
|
|
174
|
+
# @param [Hash] hash fields mapping to values
|
|
175
|
+
# @return [String] `"OK"`
|
|
176
|
+
#
|
|
177
|
+
# @see #hmset
|
|
178
|
+
def mapped_hmset(key, hash)
|
|
179
|
+
hmset(key, *hash.flatten)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Get one or multiple random fields from a hash.
|
|
183
|
+
#
|
|
184
|
+
# @example Get one random field
|
|
185
|
+
# valkey.hrandfield("hash")
|
|
186
|
+
# # => "field1"
|
|
187
|
+
# @example Get multiple random fields
|
|
188
|
+
# valkey.hrandfield("hash", 2)
|
|
189
|
+
# # => ["field1", "field2"]
|
|
190
|
+
# @example Get multiple random fields with values
|
|
191
|
+
# valkey.hrandfield("hash", 2, with_values: true)
|
|
192
|
+
# # => [["field1", "value1"], ["field2", "value2"]]
|
|
193
|
+
#
|
|
194
|
+
# @param [String] key
|
|
195
|
+
# @param [Integer] count number of fields to return (optional)
|
|
196
|
+
# @param [Hash] options
|
|
197
|
+
# - `:with_values => true`: include values in output
|
|
198
|
+
#
|
|
199
|
+
# @return [nil, String, Array<String>, Array<[String, String]>]
|
|
200
|
+
# - when `key` does not exist, `nil`
|
|
201
|
+
# - when `count` is not specified, a field name
|
|
202
|
+
# - when `count` is specified and `:with_values` is not specified, an array of field names
|
|
203
|
+
# - when `:with_values` is specified, an array with `[field, value]` pairs
|
|
204
|
+
def hrandfield(key, count = nil, withvalues: false, with_values: withvalues)
|
|
205
|
+
raise ArgumentError, "count argument must be specified" if with_values && count.nil?
|
|
206
|
+
|
|
207
|
+
args = [key]
|
|
208
|
+
args << Integer(count) if count
|
|
209
|
+
args << "WITHVALUES" if with_values
|
|
210
|
+
|
|
211
|
+
if with_values
|
|
212
|
+
send_command(RequestType::HRAND_FIELD, args) do |reply|
|
|
213
|
+
# Handle both ARRAY (flat) and MAP (already pairs) response types
|
|
214
|
+
if reply.is_a?(Array) && !reply.empty? && reply.first.is_a?(Array) && reply.first.size == 2
|
|
215
|
+
# Already in pairs format (from MAP response): [[field, value], ...]
|
|
216
|
+
reply
|
|
217
|
+
elsif reply.is_a?(Array) && reply.respond_to?(:each_slice)
|
|
218
|
+
# ARRAY response: flat array of field-value pairs, convert to pairs
|
|
219
|
+
reply.each_slice(2).to_a
|
|
220
|
+
else
|
|
221
|
+
# Fallback: try Pairify
|
|
222
|
+
Utils::Pairify.call(reply)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
else
|
|
226
|
+
send_command(RequestType::HRAND_FIELD, args)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Scan a hash
|
|
231
|
+
#
|
|
232
|
+
# @example Retrieve the first batch of key/value pairs in a hash
|
|
233
|
+
# valkey.hscan("hash", 0)
|
|
234
|
+
#
|
|
235
|
+
# @param [String] key
|
|
236
|
+
# @param [String, Integer] cursor the cursor of the iteration
|
|
237
|
+
# @param [Hash] options
|
|
238
|
+
# - `:match => String`: only return fields matching the pattern
|
|
239
|
+
# - `:count => Integer`: return count fields at most per iteration
|
|
240
|
+
#
|
|
241
|
+
# @return [String, Array<[String, String]>] the next cursor and all found key/value pairs
|
|
242
|
+
#
|
|
243
|
+
# See the [Valkey Server HSCAN documentation](https://valkey.io/commands/hscan/) for further details
|
|
244
|
+
def hscan(key, cursor, **options)
|
|
245
|
+
_scan(RequestType::HSCAN, cursor, [key], **options) do |reply|
|
|
246
|
+
[reply[0], reply[1].each_slice(2).to_a]
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Scan a hash
|
|
251
|
+
#
|
|
252
|
+
# @example Retrieve all of the key/value pairs in a hash
|
|
253
|
+
# valkey.hscan_each("hash").to_a
|
|
254
|
+
# # => [["field1", "value1"], ["field2", "value2"]]
|
|
255
|
+
#
|
|
256
|
+
# @param [String] key
|
|
257
|
+
# @param [Hash] options
|
|
258
|
+
# - `:match => String`: only return fields matching the pattern
|
|
259
|
+
# - `:count => Integer`: return count fields at most per iteration
|
|
260
|
+
#
|
|
261
|
+
# @return [Enumerator] an enumerator for all key/value pairs in the hash
|
|
262
|
+
#
|
|
263
|
+
# See the [Valkey Server HSCAN documentation](https://valkey.io/commands/hscan/) for further details
|
|
264
|
+
def hscan_each(key, **options, &block)
|
|
265
|
+
return to_enum(:hscan_each, key, **options) unless block_given?
|
|
266
|
+
|
|
267
|
+
cursor = 0
|
|
268
|
+
loop do
|
|
269
|
+
cursor, values = hscan(key, cursor, **options)
|
|
270
|
+
values.each(&block)
|
|
271
|
+
break if cursor == "0"
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Set one or more hash values.
|
|
276
|
+
#
|
|
277
|
+
# @example
|
|
278
|
+
# valkey.hset("hash", "f1", "v1", "f2", "v2") # => 2
|
|
279
|
+
# valkey.hset("hash", { "f1" => "v1", "f2" => "v2" }) # => 2
|
|
280
|
+
#
|
|
281
|
+
# @param [String] key
|
|
282
|
+
# @param [Array<String> | Hash<String, String>] attrs array or hash of fields and values
|
|
283
|
+
# @return [Integer] The number of fields that were added to the hash
|
|
284
|
+
def hset(key, *attrs)
|
|
285
|
+
attrs = attrs.first.flatten if attrs.size == 1 && attrs.first.is_a?(Hash)
|
|
286
|
+
|
|
287
|
+
send_command(RequestType::HSET, [key, *attrs])
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Set the string value of a hash field, only if the field does not exist.
|
|
291
|
+
#
|
|
292
|
+
# @example
|
|
293
|
+
# valkey.hsetnx("hash", "field", "value")
|
|
294
|
+
# # => true
|
|
295
|
+
#
|
|
296
|
+
# @param [String] key
|
|
297
|
+
# @param [String] field
|
|
298
|
+
# @param [String] value
|
|
299
|
+
# @return [Boolean] whether the field was set or not
|
|
300
|
+
def hsetnx(key, field, value)
|
|
301
|
+
send_command(RequestType::HSET_NX, [key, field, value], &Utils::Boolify)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Get the string length of the value associated with field in the hash stored at key.
|
|
305
|
+
#
|
|
306
|
+
# @example
|
|
307
|
+
# valkey.hstrlen("hash", "field")
|
|
308
|
+
# # => 5
|
|
309
|
+
#
|
|
310
|
+
# @param [String] key
|
|
311
|
+
# @param [String] field
|
|
312
|
+
# @return [Integer] the string length of the value associated with field, or 0 when field is not
|
|
313
|
+
# present in the hash or key does not exist
|
|
314
|
+
def hstrlen(key, field)
|
|
315
|
+
send_command(RequestType::HSTRLEN, [key, field])
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Get all the values in a hash.
|
|
319
|
+
#
|
|
320
|
+
# @example
|
|
321
|
+
# valkey.hvals("hash")
|
|
322
|
+
# # => ["value1", "value2"]
|
|
323
|
+
#
|
|
324
|
+
# @param [String] key
|
|
325
|
+
# @return [Array<String>] an array of values
|
|
326
|
+
def hvals(key)
|
|
327
|
+
send_command(RequestType::HVALS, [key])
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# Set the string value of a hash field and set its expiration time in seconds.
|
|
331
|
+
#
|
|
332
|
+
# @example
|
|
333
|
+
# valkey.hsetex("hash", "field", "value", 60)
|
|
334
|
+
# # => 1
|
|
335
|
+
#
|
|
336
|
+
# @param [String] key
|
|
337
|
+
# @param [String] field
|
|
338
|
+
# @param [String] value
|
|
339
|
+
# @param [Integer] seconds expiration time in seconds
|
|
340
|
+
# @return [Integer] the number of fields that were added
|
|
341
|
+
def hsetex(key, field, value, seconds)
|
|
342
|
+
send_command(RequestType::HSETEX, [key, field, value, Integer(seconds)])
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Get the value of one or more hash fields and optionally set their expiration time.
|
|
346
|
+
#
|
|
347
|
+
# @example
|
|
348
|
+
# valkey.hgetex("hash", "field1", "field2", ex: 60)
|
|
349
|
+
# # => ["value1", "value2"]
|
|
350
|
+
#
|
|
351
|
+
# @param [String] key
|
|
352
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
353
|
+
# @param [Hash] options
|
|
354
|
+
# - `:ex => Integer`: Set the specified expire time, in seconds.
|
|
355
|
+
# - `:px => Integer`: Set the specified expire time, in milliseconds.
|
|
356
|
+
# - `:exat => Integer`: Set the specified Unix time at which the field will expire, in seconds.
|
|
357
|
+
# - `:pxat => Integer`: Set the specified Unix time at which the field will expire, in milliseconds.
|
|
358
|
+
# - `:persist => true`: Remove the time to live associated with the field.
|
|
359
|
+
# @return [String, Array<String, nil>] The value of the field for single field, or array of values
|
|
360
|
+
# for multiple fields. For every field that does not exist in the hash, a nil value is returned.
|
|
361
|
+
def hgetex(key, *fields, ex: nil, px: nil, exat: nil, pxat: nil, persist: false)
|
|
362
|
+
fields.flatten!(1)
|
|
363
|
+
args = [key, "FIELDS", fields.length, *fields]
|
|
364
|
+
args << "EX" << ex if ex
|
|
365
|
+
args << "PX" << px if px
|
|
366
|
+
args << "EXAT" << exat if exat
|
|
367
|
+
args << "PXAT" << pxat if pxat
|
|
368
|
+
args << "PERSIST" if persist
|
|
369
|
+
|
|
370
|
+
send_command(RequestType::HGETEX, args) do |reply|
|
|
371
|
+
fields.length == 1 ? reply[0] : reply
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# Set a timeout on one or more hash fields.
|
|
376
|
+
#
|
|
377
|
+
# @example
|
|
378
|
+
# valkey.hexpire("hash", 60, "field1", "field2")
|
|
379
|
+
# # => [1, 1]
|
|
380
|
+
#
|
|
381
|
+
# @param [String] key
|
|
382
|
+
# @param [Integer] seconds time to live in seconds
|
|
383
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
384
|
+
# @param [Hash] options
|
|
385
|
+
# - `:nx => true`: Set expiry only when the field has no expiry.
|
|
386
|
+
# - `:xx => true`: Set expiry only when the field has an existing expiry.
|
|
387
|
+
# - `:gt => true`: Set expiry only when the new expiry is greater than current one.
|
|
388
|
+
# - `:lt => true`: Set expiry only when the new expiry is less than current one.
|
|
389
|
+
# @return [Array<Integer>] Array of results for each field.
|
|
390
|
+
# - `1` if the expiration time was successfully set for the field.
|
|
391
|
+
# - `0` if the specified condition was not met.
|
|
392
|
+
# - `-2` if the field does not exist in the HASH, or key does not exist.
|
|
393
|
+
def hexpire(key, seconds, *fields, nx: nil, xx: nil, gt: nil, lt: nil)
|
|
394
|
+
fields.flatten!(1)
|
|
395
|
+
args = [key, Integer(seconds), "FIELDS", fields.length, *fields]
|
|
396
|
+
args << "NX" if nx
|
|
397
|
+
args << "XX" if xx
|
|
398
|
+
args << "GT" if gt
|
|
399
|
+
args << "LT" if lt
|
|
400
|
+
|
|
401
|
+
send_command(RequestType::HEXPIRE, args)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# Set the expiration for one or more hash fields as a UNIX timestamp.
|
|
405
|
+
#
|
|
406
|
+
# @example
|
|
407
|
+
# valkey.hexpireat("hash", Time.now.to_i + 60, "field1", "field2")
|
|
408
|
+
# # => [1, 1]
|
|
409
|
+
#
|
|
410
|
+
# @param [String] key
|
|
411
|
+
# @param [Integer] unix_time expiry time specified as a UNIX timestamp in seconds
|
|
412
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
413
|
+
# @param [Hash] options
|
|
414
|
+
# - `:nx => true`: Set expiry only when the field has no expiry.
|
|
415
|
+
# - `:xx => true`: Set expiry only when the field has an existing expiry.
|
|
416
|
+
# - `:gt => true`: Set expiry only when the new expiry is greater than current one.
|
|
417
|
+
# - `:lt => true`: Set expiry only when the new expiry is less than current one.
|
|
418
|
+
# @return [Array<Integer>] Array of results for each field.
|
|
419
|
+
# - `1` if the expiration time was successfully set for the field.
|
|
420
|
+
# - `0` if the specified condition was not met.
|
|
421
|
+
# - `-2` if the field does not exist in the HASH, or key does not exist.
|
|
422
|
+
def hexpireat(key, unix_time, *fields, nx: nil, xx: nil, gt: nil, lt: nil)
|
|
423
|
+
fields.flatten!(1)
|
|
424
|
+
args = [key, Integer(unix_time), "FIELDS", fields.length, *fields]
|
|
425
|
+
args << "NX" if nx
|
|
426
|
+
args << "XX" if xx
|
|
427
|
+
args << "GT" if gt
|
|
428
|
+
args << "LT" if lt
|
|
429
|
+
|
|
430
|
+
send_command(RequestType::HEXPIREAT, args)
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
# Set a timeout on one or more hash fields in milliseconds.
|
|
434
|
+
#
|
|
435
|
+
# @example
|
|
436
|
+
# valkey.hpexpire("hash", 60000, "field1", "field2")
|
|
437
|
+
# # => [1, 1]
|
|
438
|
+
#
|
|
439
|
+
# @param [String] key
|
|
440
|
+
# @param [Integer] milliseconds time to live in milliseconds
|
|
441
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
442
|
+
# @param [Hash] options
|
|
443
|
+
# - `:nx => true`: Set expiry only when the field has no expiry.
|
|
444
|
+
# - `:xx => true`: Set expiry only when the field has an existing expiry.
|
|
445
|
+
# - `:gt => true`: Set expiry only when the new expiry is greater than current one.
|
|
446
|
+
# - `:lt => true`: Set expiry only when the new expiry is less than current one.
|
|
447
|
+
# @return [Array<Integer>] Array of results for each field.
|
|
448
|
+
# - `1` if the expiration time was successfully set for the field.
|
|
449
|
+
# - `0` if the specified condition was not met.
|
|
450
|
+
# - `-2` if the field does not exist in the HASH, or key does not exist.
|
|
451
|
+
def hpexpire(key, milliseconds, *fields, nx: nil, xx: nil, gt: nil, lt: nil)
|
|
452
|
+
fields.flatten!(1)
|
|
453
|
+
args = [key, Integer(milliseconds), "FIELDS", fields.length, *fields]
|
|
454
|
+
args << "NX" if nx
|
|
455
|
+
args << "XX" if xx
|
|
456
|
+
args << "GT" if gt
|
|
457
|
+
args << "LT" if lt
|
|
458
|
+
|
|
459
|
+
send_command(RequestType::HPEXPIRE, args)
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# Set the expiration for one or more hash fields as a UNIX timestamp in milliseconds.
|
|
463
|
+
#
|
|
464
|
+
# @example
|
|
465
|
+
# valkey.hpexpireat("hash", (Time.now.to_i * 1000) + 60000, "field1", "field2")
|
|
466
|
+
# # => [1, 1]
|
|
467
|
+
#
|
|
468
|
+
# @param [String] key
|
|
469
|
+
# @param [Integer] unix_time_ms expiry time specified as a UNIX timestamp in milliseconds
|
|
470
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
471
|
+
# @param [Hash] options
|
|
472
|
+
# - `:nx => true`: Set expiry only when the field has no expiry.
|
|
473
|
+
# - `:xx => true`: Set expiry only when the field has an existing expiry.
|
|
474
|
+
# - `:gt => true`: Set expiry only when the new expiry is greater than current one.
|
|
475
|
+
# - `:lt => true`: Set expiry only when the new expiry is less than current one.
|
|
476
|
+
# @return [Array<Integer>] Array of results for each field.
|
|
477
|
+
# - `1` if the expiration time was successfully set for the field.
|
|
478
|
+
# - `0` if the specified condition was not met.
|
|
479
|
+
# - `-2` if the field does not exist in the HASH, or key does not exist.
|
|
480
|
+
def hpexpireat(key, unix_time_ms, *fields, nx: nil, xx: nil, gt: nil, lt: nil)
|
|
481
|
+
fields.flatten!(1)
|
|
482
|
+
args = [key, Integer(unix_time_ms), "FIELDS", fields.length, *fields]
|
|
483
|
+
args << "NX" if nx
|
|
484
|
+
args << "XX" if xx
|
|
485
|
+
args << "GT" if gt
|
|
486
|
+
args << "LT" if lt
|
|
487
|
+
|
|
488
|
+
send_command(RequestType::HPEXPIREAT, args)
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
# Remove the expiration from one or more hash fields.
|
|
492
|
+
#
|
|
493
|
+
# @example
|
|
494
|
+
# valkey.hpersist("hash", "field1", "field2")
|
|
495
|
+
# # => [1, 1]
|
|
496
|
+
#
|
|
497
|
+
# @param [String] key
|
|
498
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
499
|
+
# @return [Array<Integer>] Array of results for each field.
|
|
500
|
+
# - `1` if the expiration time was successfully removed from the field.
|
|
501
|
+
# - `-1` if the field exists but has no expiration time.
|
|
502
|
+
# - `-2` if the field does not exist in the provided hash key, or the hash key does not exist.
|
|
503
|
+
def hpersist(key, *fields)
|
|
504
|
+
fields.flatten!(1)
|
|
505
|
+
args = [key, "FIELDS", fields.length, *fields]
|
|
506
|
+
|
|
507
|
+
send_command(RequestType::HPERSIST, args)
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
# Get the time to live in seconds of one or more hash fields.
|
|
511
|
+
#
|
|
512
|
+
# @example
|
|
513
|
+
# valkey.httl("hash", "field1", "field2")
|
|
514
|
+
# # => [60, -1]
|
|
515
|
+
#
|
|
516
|
+
# @param [String] key
|
|
517
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
518
|
+
# @return [Array<Integer>] Array of TTLs in seconds for each field.
|
|
519
|
+
# - TTL in seconds if the field exists and has a timeout.
|
|
520
|
+
# - `-1` if the field exists but has no associated expire.
|
|
521
|
+
# - `-2` if the field does not exist in the provided hash key, or the hash key is empty.
|
|
522
|
+
def httl(key, *fields)
|
|
523
|
+
fields.flatten!(1)
|
|
524
|
+
args = [key, "FIELDS", fields.length, *fields]
|
|
525
|
+
|
|
526
|
+
send_command(RequestType::HTTL, args)
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
# Get the time to live in milliseconds of one or more hash fields.
|
|
530
|
+
#
|
|
531
|
+
# @example
|
|
532
|
+
# valkey.hpttl("hash", "field1", "field2")
|
|
533
|
+
# # => [60000, -1]
|
|
534
|
+
#
|
|
535
|
+
# @param [String] key
|
|
536
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
537
|
+
# @return [Array<Integer>] Array of TTLs in milliseconds for each field.
|
|
538
|
+
# - TTL in milliseconds if the field exists and has a timeout.
|
|
539
|
+
# - `-1` if the field exists but has no associated expire.
|
|
540
|
+
# - `-2` if the field does not exist in the provided hash key, or the hash key is empty.
|
|
541
|
+
def hpttl(key, *fields)
|
|
542
|
+
fields.flatten!(1)
|
|
543
|
+
args = [key, "FIELDS", fields.length, *fields]
|
|
544
|
+
|
|
545
|
+
send_command(RequestType::HPTTL, args)
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
# Get the expiration Unix timestamp in seconds for one or more hash fields.
|
|
549
|
+
#
|
|
550
|
+
# @example
|
|
551
|
+
# valkey.hexpiretime("hash", "field1", "field2")
|
|
552
|
+
# # => [1234567890, -1]
|
|
553
|
+
#
|
|
554
|
+
# @param [String] key
|
|
555
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
556
|
+
# @return [Array<Integer>] Array of expiration timestamps in seconds for each field.
|
|
557
|
+
# - Expiration Unix timestamp in seconds if the field exists and has a timeout.
|
|
558
|
+
# - `-1` if the field exists but has no associated expire.
|
|
559
|
+
# - `-2` if the field does not exist in the provided hash key, or the hash key is empty.
|
|
560
|
+
def hexpiretime(key, *fields)
|
|
561
|
+
fields.flatten!(1)
|
|
562
|
+
args = [key, "FIELDS", fields.length, *fields]
|
|
563
|
+
|
|
564
|
+
send_command(RequestType::HEXPIRETIME, args)
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
# Get the expiration Unix timestamp in milliseconds for one or more hash fields.
|
|
568
|
+
#
|
|
569
|
+
# @example
|
|
570
|
+
# valkey.hpexpiretime("hash", "field1", "field2")
|
|
571
|
+
# # => [1234567890000, -1]
|
|
572
|
+
#
|
|
573
|
+
# @param [String] key
|
|
574
|
+
# @param [String, Array<String>] fields one field, or array of fields
|
|
575
|
+
# @return [Array<Integer>] Array of expiration timestamps in milliseconds for each field.
|
|
576
|
+
# - Expiration Unix timestamp in milliseconds if the field exists and has a timeout.
|
|
577
|
+
# - `-1` if the field exists but has no associated expire.
|
|
578
|
+
# - `-2` if the field does not exist in the provided hash key, or the hash key is empty.
|
|
579
|
+
def hpexpiretime(key, *fields)
|
|
580
|
+
fields.flatten!(1)
|
|
581
|
+
args = [key, "FIELDS", fields.length, *fields]
|
|
582
|
+
|
|
583
|
+
send_command(RequestType::HPEXPIRETIME, args)
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Valkey
|
|
4
|
+
module Commands
|
|
5
|
+
module HyperLogLogCommands
|
|
6
|
+
# Add one or more members to a HyperLogLog structure.
|
|
7
|
+
#
|
|
8
|
+
# @param [String] key
|
|
9
|
+
# @param [String, Array<String>] member one member, or array of members
|
|
10
|
+
# @return [Boolean] true if at least 1 HyperLogLog internal register was altered. false otherwise.
|
|
11
|
+
#
|
|
12
|
+
# @see https://valkey.io/commands/pfadd/
|
|
13
|
+
def pfadd(key, member)
|
|
14
|
+
args = [key]
|
|
15
|
+
|
|
16
|
+
if member.is_a?(Array)
|
|
17
|
+
args += member
|
|
18
|
+
else
|
|
19
|
+
args << member
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
send_command(RequestType::PFADD, args)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Get the approximate cardinality of members added to HyperLogLog structure.
|
|
26
|
+
#
|
|
27
|
+
# If called with multiple keys, returns the approximate cardinality of the
|
|
28
|
+
# union of the HyperLogLogs contained in the keys.
|
|
29
|
+
#
|
|
30
|
+
# @param [String, Array<String>] keys
|
|
31
|
+
# @return [Integer]
|
|
32
|
+
#
|
|
33
|
+
# @see https://valkey.io/commands/pfcount
|
|
34
|
+
def pfcount(*keys)
|
|
35
|
+
send_command(RequestType::PFCOUNT, keys.flatten(1))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
|
|
39
|
+
# the observed Sets of the source HyperLogLog structures.
|
|
40
|
+
#
|
|
41
|
+
# @param [String] dest_key destination key
|
|
42
|
+
# @param [String, Array<String>] source_key source key, or array of keys
|
|
43
|
+
# @return [Boolean]
|
|
44
|
+
#
|
|
45
|
+
# @see https://valkey.io/commands/pfmerge
|
|
46
|
+
def pfmerge(dest_key, *source_key)
|
|
47
|
+
send_command(RequestType::PFMERGE, [dest_key, *source_key], &Utils::BoolifySet)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|