redis 4.7.1 → 5.4.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 +4 -4
- data/CHANGELOG.md +93 -0
- data/README.md +125 -162
- data/lib/redis/client.rb +82 -625
- data/lib/redis/commands/bitmaps.rb +14 -4
- data/lib/redis/commands/cluster.rb +1 -18
- data/lib/redis/commands/connection.rb +5 -10
- data/lib/redis/commands/geo.rb +3 -3
- data/lib/redis/commands/hashes.rb +13 -6
- data/lib/redis/commands/hyper_log_log.rb +1 -1
- data/lib/redis/commands/keys.rb +75 -27
- data/lib/redis/commands/lists.rb +73 -23
- data/lib/redis/commands/pubsub.rb +34 -25
- data/lib/redis/commands/server.rb +15 -15
- data/lib/redis/commands/sets.rb +47 -36
- data/lib/redis/commands/sorted_sets.rb +128 -18
- data/lib/redis/commands/streams.rb +48 -21
- data/lib/redis/commands/strings.rb +18 -17
- data/lib/redis/commands/transactions.rb +7 -31
- data/lib/redis/commands.rb +11 -14
- data/lib/redis/distributed.rb +150 -75
- data/lib/redis/errors.rb +15 -50
- data/lib/redis/hash_ring.rb +26 -26
- data/lib/redis/pipeline.rb +47 -222
- data/lib/redis/subscribe.rb +50 -14
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +76 -182
- metadata +10 -57
- data/lib/redis/cluster/command.rb +0 -79
- data/lib/redis/cluster/command_loader.rb +0 -33
- data/lib/redis/cluster/key_slot_converter.rb +0 -72
- data/lib/redis/cluster/node.rb +0 -120
- data/lib/redis/cluster/node_key.rb +0 -31
- data/lib/redis/cluster/node_loader.rb +0 -34
- data/lib/redis/cluster/option.rb +0 -100
- data/lib/redis/cluster/slot.rb +0 -86
- data/lib/redis/cluster/slot_loader.rb +0 -46
- data/lib/redis/cluster.rb +0 -315
- data/lib/redis/connection/command_helper.rb +0 -41
- data/lib/redis/connection/hiredis.rb +0 -66
- data/lib/redis/connection/registry.rb +0 -13
- data/lib/redis/connection/ruby.rb +0 -437
- data/lib/redis/connection/synchrony.rb +0 -148
- data/lib/redis/connection.rb +0 -11
@@ -36,7 +36,7 @@ class Redis
|
|
36
36
|
#
|
37
37
|
# @param [String, Symbol] subcommand e.g. `kill`, `list`, `getname`, `setname`
|
38
38
|
# @return [String, Hash] depends on subcommand
|
39
|
-
def client(subcommand
|
39
|
+
def client(subcommand, *args)
|
40
40
|
send_command([:client, subcommand] + args) do |reply|
|
41
41
|
if subcommand.to_s == "list"
|
42
42
|
reply.lines.map do |line|
|
@@ -117,9 +117,13 @@ class Redis
|
|
117
117
|
#
|
118
118
|
# @yield a block to be called for every line of output
|
119
119
|
# @yieldparam [String] line timestamp and command that was executed
|
120
|
-
def monitor
|
120
|
+
def monitor
|
121
121
|
synchronize do |client|
|
122
|
-
client.
|
122
|
+
client = client.pubsub
|
123
|
+
client.call_v([:monitor])
|
124
|
+
loop do
|
125
|
+
yield client.next_event
|
126
|
+
end
|
123
127
|
end
|
124
128
|
end
|
125
129
|
|
@@ -133,13 +137,11 @@ class Redis
|
|
133
137
|
# Synchronously save the dataset to disk and then shut down the server.
|
134
138
|
def shutdown
|
135
139
|
synchronize do |client|
|
136
|
-
client.
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
nil
|
142
|
-
end
|
140
|
+
client.disable_reconnection do
|
141
|
+
client.call_v([:shutdown])
|
142
|
+
rescue ConnectionError
|
143
|
+
# This means Redis has probably exited.
|
144
|
+
nil
|
143
145
|
end
|
144
146
|
end
|
145
147
|
end
|
@@ -155,11 +157,9 @@ class Redis
|
|
155
157
|
# @param [Integer] length maximum number of entries to return
|
156
158
|
# @return [Array<String>, Integer, String] depends on subcommand
|
157
159
|
def slowlog(subcommand, length = nil)
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
client.call args
|
162
|
-
end
|
160
|
+
args = [:slowlog, subcommand]
|
161
|
+
args << Integer(length) if length
|
162
|
+
send_command(args)
|
163
163
|
end
|
164
164
|
|
165
165
|
# Internal command used for replication.
|
data/lib/redis/commands/sets.rb
CHANGED
@@ -15,40 +15,40 @@ class Redis
|
|
15
15
|
#
|
16
16
|
# @param [String] key
|
17
17
|
# @param [String, Array<String>] member one member, or array of members
|
18
|
-
# @return [
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
18
|
+
# @return [Integer] The number of members that were successfully added
|
19
|
+
def sadd(key, *members)
|
20
|
+
members.flatten!(1)
|
21
|
+
send_command([:sadd, key].concat(members))
|
22
|
+
end
|
23
|
+
|
24
|
+
# Add one or more members to a set.
|
25
|
+
#
|
26
|
+
# @param [String] key
|
27
|
+
# @param [String, Array<String>] member one member, or array of members
|
28
|
+
# @return [Boolean] Wether at least one member was successfully added.
|
29
|
+
def sadd?(key, *members)
|
30
|
+
members.flatten!(1)
|
31
|
+
send_command([:sadd, key].concat(members), &Boolify)
|
32
32
|
end
|
33
33
|
|
34
34
|
# Remove one or more members from a set.
|
35
35
|
#
|
36
36
|
# @param [String] key
|
37
37
|
# @param [String, Array<String>] member one member, or array of members
|
38
|
-
# @return [
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
38
|
+
# @return [Integer] The number of members that were successfully removed
|
39
|
+
def srem(key, *members)
|
40
|
+
members.flatten!(1)
|
41
|
+
send_command([:srem, key].concat(members))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Remove one or more members from a set.
|
45
|
+
#
|
46
|
+
# @param [String] key
|
47
|
+
# @param [String, Array<String>] member one member, or array of members
|
48
|
+
# @return [Boolean] Wether at least one member was successfully removed.
|
49
|
+
def srem?(key, *members)
|
50
|
+
members.flatten!(1)
|
51
|
+
send_command([:srem, key].concat(members), &Boolify)
|
52
52
|
end
|
53
53
|
|
54
54
|
# Remove and return one or more random member from a set.
|
@@ -60,7 +60,7 @@ class Redis
|
|
60
60
|
if count.nil?
|
61
61
|
send_command([:spop, key])
|
62
62
|
else
|
63
|
-
send_command([:spop, key, count])
|
63
|
+
send_command([:spop, key, Integer(count)])
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -102,7 +102,8 @@ class Redis
|
|
102
102
|
# @param [String, Array<String>] members
|
103
103
|
# @return [Array<Boolean>]
|
104
104
|
def smismember(key, *members)
|
105
|
-
|
105
|
+
members.flatten!(1)
|
106
|
+
send_command([:smismember, key].concat(members)) do |reply|
|
106
107
|
reply.map(&Boolify)
|
107
108
|
end
|
108
109
|
end
|
@@ -120,7 +121,8 @@ class Redis
|
|
120
121
|
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
121
122
|
# @return [Array<String>] members in the difference
|
122
123
|
def sdiff(*keys)
|
123
|
-
|
124
|
+
keys.flatten!(1)
|
125
|
+
send_command([:sdiff].concat(keys))
|
124
126
|
end
|
125
127
|
|
126
128
|
# Subtract multiple sets and store the resulting set in a key.
|
@@ -129,7 +131,8 @@ class Redis
|
|
129
131
|
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
130
132
|
# @return [Integer] number of elements in the resulting set
|
131
133
|
def sdiffstore(destination, *keys)
|
132
|
-
|
134
|
+
keys.flatten!(1)
|
135
|
+
send_command([:sdiffstore, destination].concat(keys))
|
133
136
|
end
|
134
137
|
|
135
138
|
# Intersect multiple sets.
|
@@ -137,7 +140,8 @@ class Redis
|
|
137
140
|
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
138
141
|
# @return [Array<String>] members in the intersection
|
139
142
|
def sinter(*keys)
|
140
|
-
|
143
|
+
keys.flatten!(1)
|
144
|
+
send_command([:sinter].concat(keys))
|
141
145
|
end
|
142
146
|
|
143
147
|
# Intersect multiple sets and store the resulting set in a key.
|
@@ -146,7 +150,8 @@ class Redis
|
|
146
150
|
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
147
151
|
# @return [Integer] number of elements in the resulting set
|
148
152
|
def sinterstore(destination, *keys)
|
149
|
-
|
153
|
+
keys.flatten!(1)
|
154
|
+
send_command([:sinterstore, destination].concat(keys))
|
150
155
|
end
|
151
156
|
|
152
157
|
# Add multiple sets.
|
@@ -154,7 +159,8 @@ class Redis
|
|
154
159
|
# @param [String, Array<String>] keys keys pointing to sets to unify
|
155
160
|
# @return [Array<String>] members in the union
|
156
161
|
def sunion(*keys)
|
157
|
-
|
162
|
+
keys.flatten!(1)
|
163
|
+
send_command([:sunion].concat(keys))
|
158
164
|
end
|
159
165
|
|
160
166
|
# Add multiple sets and store the resulting set in a key.
|
@@ -163,7 +169,8 @@ class Redis
|
|
163
169
|
# @param [String, Array<String>] keys keys pointing to sets to unify
|
164
170
|
# @return [Integer] number of elements in the resulting set
|
165
171
|
def sunionstore(destination, *keys)
|
166
|
-
|
172
|
+
keys.flatten!(1)
|
173
|
+
send_command([:sunionstore, destination].concat(keys))
|
167
174
|
end
|
168
175
|
|
169
176
|
# Scan a set
|
@@ -177,6 +184,8 @@ class Redis
|
|
177
184
|
# - `:count => Integer`: return count keys at most per iteration
|
178
185
|
#
|
179
186
|
# @return [String, Array<String>] the next cursor and all found members
|
187
|
+
#
|
188
|
+
# See the [Redis Server SSCAN documentation](https://redis.io/docs/latest/commands/sscan/) for further details
|
180
189
|
def sscan(key, cursor, **options)
|
181
190
|
_scan(:sscan, cursor, [key], **options)
|
182
191
|
end
|
@@ -192,6 +201,8 @@ class Redis
|
|
192
201
|
# - `:count => Integer`: return count keys at most per iteration
|
193
202
|
#
|
194
203
|
# @return [Enumerator] an enumerator for all keys in the set
|
204
|
+
#
|
205
|
+
# See the [Redis Server SSCAN documentation](https://redis.io/docs/latest/commands/sscan/) for further details
|
195
206
|
def sscan_each(key, **options, &block)
|
196
207
|
return to_enum(:sscan_each, key, **options) unless block_given?
|
197
208
|
|
@@ -136,7 +136,9 @@ class Redis
|
|
136
136
|
# @return [Array<String, Float>] element and score pair if count is not specified
|
137
137
|
# @return [Array<Array<String, Float>>] list of popped elements and scores
|
138
138
|
def zpopmax(key, count = nil)
|
139
|
-
|
139
|
+
command = [:zpopmax, key]
|
140
|
+
command << Integer(count) if count
|
141
|
+
send_command(command) do |members|
|
140
142
|
members = FloatifyPairs.call(members)
|
141
143
|
count.to_i > 1 ? members : members.first
|
142
144
|
end
|
@@ -157,12 +159,80 @@ class Redis
|
|
157
159
|
# @return [Array<String, Float>] element and score pair if count is not specified
|
158
160
|
# @return [Array<Array<String, Float>>] list of popped elements and scores
|
159
161
|
def zpopmin(key, count = nil)
|
160
|
-
|
162
|
+
command = [:zpopmin, key]
|
163
|
+
command << Integer(count) if count
|
164
|
+
send_command(command) do |members|
|
161
165
|
members = FloatifyPairs.call(members)
|
162
166
|
count.to_i > 1 ? members : members.first
|
163
167
|
end
|
164
168
|
end
|
165
169
|
|
170
|
+
# Removes and returns up to count members with scores in the sorted set stored at key.
|
171
|
+
#
|
172
|
+
# @example Popping a member
|
173
|
+
# redis.bzmpop('zset')
|
174
|
+
# #=> ['zset', ['a', 1.0]]
|
175
|
+
# @example With count option
|
176
|
+
# redis.bzmpop('zset', count: 2)
|
177
|
+
# #=> ['zset', [['a', 1.0], ['b', 2.0]]
|
178
|
+
#
|
179
|
+
# @params timeout [Float] a float value specifying the maximum number of seconds to block) elapses.
|
180
|
+
# A timeout of zero can be used to block indefinitely.
|
181
|
+
# @params key [String, Array<String>] one or more keys with sorted sets
|
182
|
+
# @params modifier [String]
|
183
|
+
# - when `"MIN"` - the elements popped are those with lowest scores
|
184
|
+
# - when `"MAX"` - the elements popped are those with the highest scores
|
185
|
+
# @params count [Integer] a number of members to pop
|
186
|
+
#
|
187
|
+
# @return [Array<String, Array<String, Float>>] list of popped elements and scores
|
188
|
+
def bzmpop(timeout, *keys, modifier: "MIN", count: nil)
|
189
|
+
raise ArgumentError, "Pick either MIN or MAX" unless modifier == "MIN" || modifier == "MAX"
|
190
|
+
|
191
|
+
args = [:bzmpop, timeout, keys.size, *keys, modifier]
|
192
|
+
args << "COUNT" << Integer(count) if count
|
193
|
+
|
194
|
+
send_blocking_command(args, timeout) do |response|
|
195
|
+
response&.map do |entry|
|
196
|
+
case entry
|
197
|
+
when String then entry
|
198
|
+
when Array then entry.map { |pair| FloatifyPairs.call(pair) }.flatten(1)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Removes and returns up to count members with scores in the sorted set stored at key.
|
205
|
+
#
|
206
|
+
# @example Popping a member
|
207
|
+
# redis.zmpop('zset')
|
208
|
+
# #=> ['zset', ['a', 1.0]]
|
209
|
+
# @example With count option
|
210
|
+
# redis.zmpop('zset', count: 2)
|
211
|
+
# #=> ['zset', [['a', 1.0], ['b', 2.0]]
|
212
|
+
#
|
213
|
+
# @params key [String, Array<String>] one or more keys with sorted sets
|
214
|
+
# @params modifier [String]
|
215
|
+
# - when `"MIN"` - the elements popped are those with lowest scores
|
216
|
+
# - when `"MAX"` - the elements popped are those with the highest scores
|
217
|
+
# @params count [Integer] a number of members to pop
|
218
|
+
#
|
219
|
+
# @return [Array<String, Array<String, Float>>] list of popped elements and scores
|
220
|
+
def zmpop(*keys, modifier: "MIN", count: nil)
|
221
|
+
raise ArgumentError, "Pick either MIN or MAX" unless modifier == "MIN" || modifier == "MAX"
|
222
|
+
|
223
|
+
args = [:zmpop, keys.size, *keys, modifier]
|
224
|
+
args << "COUNT" << Integer(count) if count
|
225
|
+
|
226
|
+
send_command(args) do |response|
|
227
|
+
response&.map do |entry|
|
228
|
+
case entry
|
229
|
+
when String then entry
|
230
|
+
when Array then entry.map { |pair| FloatifyPairs.call(pair) }.flatten(1)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
166
236
|
# Removes and returns up to count members with the highest scores in the sorted set stored at keys,
|
167
237
|
# or block until one is available.
|
168
238
|
#
|
@@ -261,7 +331,7 @@ class Redis
|
|
261
331
|
end
|
262
332
|
|
263
333
|
args = [:zrandmember, key]
|
264
|
-
args << count if count
|
334
|
+
args << Integer(count) if count
|
265
335
|
|
266
336
|
if with_scores
|
267
337
|
args << "WITHSCORES"
|
@@ -313,7 +383,7 @@ class Redis
|
|
313
383
|
|
314
384
|
if limit
|
315
385
|
args << "LIMIT"
|
316
|
-
args.concat(limit)
|
386
|
+
args.concat(limit.map { |l| Integer(l) })
|
317
387
|
end
|
318
388
|
|
319
389
|
if with_scores
|
@@ -354,7 +424,7 @@ class Redis
|
|
354
424
|
|
355
425
|
if limit
|
356
426
|
args << "LIMIT"
|
357
|
-
args.concat(limit)
|
427
|
+
args.concat(limit.map { |l| Integer(l) })
|
358
428
|
end
|
359
429
|
|
360
430
|
send_command(args)
|
@@ -372,7 +442,7 @@ class Redis
|
|
372
442
|
#
|
373
443
|
# @see #zrange
|
374
444
|
def zrevrange(key, start, stop, withscores: false, with_scores: withscores)
|
375
|
-
args = [:zrevrange, key, start, stop]
|
445
|
+
args = [:zrevrange, key, Integer(start), Integer(stop)]
|
376
446
|
|
377
447
|
if with_scores
|
378
448
|
args << "WITHSCORES"
|
@@ -384,21 +454,55 @@ class Redis
|
|
384
454
|
|
385
455
|
# Determine the index of a member in a sorted set.
|
386
456
|
#
|
457
|
+
# @example Retrieve member rank
|
458
|
+
# redis.zrank("zset", "a")
|
459
|
+
# # => 3
|
460
|
+
# @example Retrieve member rank with their score
|
461
|
+
# redis.zrank("zset", "a", :with_score => true)
|
462
|
+
# # => [3, 32.0]
|
463
|
+
#
|
387
464
|
# @param [String] key
|
388
465
|
# @param [String] member
|
389
|
-
#
|
390
|
-
|
391
|
-
|
466
|
+
#
|
467
|
+
# @return [Integer, [Integer, Float]]
|
468
|
+
# - when `:with_score` is not specified, an Integer
|
469
|
+
# - when `:with_score` is specified, a `[rank, score]` pair
|
470
|
+
def zrank(key, member, withscore: false, with_score: withscore)
|
471
|
+
args = [:zrank, key, member]
|
472
|
+
|
473
|
+
if with_score
|
474
|
+
args << "WITHSCORE"
|
475
|
+
block = FloatifyPair
|
476
|
+
end
|
477
|
+
|
478
|
+
send_command(args, &block)
|
392
479
|
end
|
393
480
|
|
394
481
|
# Determine the index of a member in a sorted set, with scores ordered from
|
395
482
|
# high to low.
|
396
483
|
#
|
484
|
+
# @example Retrieve member rank
|
485
|
+
# redis.zrevrank("zset", "a")
|
486
|
+
# # => 3
|
487
|
+
# @example Retrieve member rank with their score
|
488
|
+
# redis.zrevrank("zset", "a", :with_score => true)
|
489
|
+
# # => [3, 32.0]
|
490
|
+
#
|
397
491
|
# @param [String] key
|
398
492
|
# @param [String] member
|
399
|
-
#
|
400
|
-
|
401
|
-
|
493
|
+
#
|
494
|
+
# @return [Integer, [Integer, Float]]
|
495
|
+
# - when `:with_score` is not specified, an Integer
|
496
|
+
# - when `:with_score` is specified, a `[rank, score]` pair
|
497
|
+
def zrevrank(key, member, withscore: false, with_score: withscore)
|
498
|
+
args = [:zrevrank, key, member]
|
499
|
+
|
500
|
+
if with_score
|
501
|
+
args << "WITHSCORE"
|
502
|
+
block = FloatifyPair
|
503
|
+
end
|
504
|
+
|
505
|
+
send_command(args, &block)
|
402
506
|
end
|
403
507
|
|
404
508
|
# Remove all members in a sorted set within the given indexes.
|
@@ -466,7 +570,7 @@ class Redis
|
|
466
570
|
|
467
571
|
if limit
|
468
572
|
args << "LIMIT"
|
469
|
-
args.concat(limit)
|
573
|
+
args.concat(limit.map { |l| Integer(l) })
|
470
574
|
end
|
471
575
|
|
472
576
|
send_command(args)
|
@@ -488,7 +592,7 @@ class Redis
|
|
488
592
|
|
489
593
|
if limit
|
490
594
|
args << "LIMIT"
|
491
|
-
args.concat(limit)
|
595
|
+
args.concat(limit.map { |l| Integer(l) })
|
492
596
|
end
|
493
597
|
|
494
598
|
send_command(args)
|
@@ -531,7 +635,7 @@ class Redis
|
|
531
635
|
|
532
636
|
if limit
|
533
637
|
args << "LIMIT"
|
534
|
-
args.concat(limit)
|
638
|
+
args.concat(limit.map { |l| Integer(l) })
|
535
639
|
end
|
536
640
|
|
537
641
|
send_command(args, &block)
|
@@ -561,7 +665,7 @@ class Redis
|
|
561
665
|
|
562
666
|
if limit
|
563
667
|
args << "LIMIT"
|
564
|
-
args.concat(limit)
|
668
|
+
args.concat(limit.map { |l| Integer(l) })
|
565
669
|
end
|
566
670
|
|
567
671
|
send_command(args, &block)
|
@@ -747,6 +851,8 @@ class Redis
|
|
747
851
|
#
|
748
852
|
# @return [String, Array<[String, Float]>] the next cursor and all found
|
749
853
|
# members and scores
|
854
|
+
#
|
855
|
+
# See the [Redis Server ZSCAN documentation](https://redis.io/docs/latest/commands/zscan/) for further details
|
750
856
|
def zscan(key, cursor, **options)
|
751
857
|
_scan(:zscan, cursor, [key], **options) do |reply|
|
752
858
|
[reply[0], FloatifyPairs.call(reply[1])]
|
@@ -764,6 +870,8 @@ class Redis
|
|
764
870
|
# - `:count => Integer`: return count keys at most per iteration
|
765
871
|
#
|
766
872
|
# @return [Enumerator] an enumerator for all found scores and members
|
873
|
+
#
|
874
|
+
# See the [Redis Server ZSCAN documentation](https://redis.io/docs/latest/commands/zscan/) for further details
|
767
875
|
def zscan_each(key, **options, &block)
|
768
876
|
return to_enum(:zscan_each, key, **options) unless block_given?
|
769
877
|
|
@@ -778,7 +886,8 @@ class Redis
|
|
778
886
|
private
|
779
887
|
|
780
888
|
def _zsets_operation(cmd, *keys, weights: nil, aggregate: nil, with_scores: false)
|
781
|
-
|
889
|
+
keys.flatten!(1)
|
890
|
+
command = [cmd, keys.size].concat(keys)
|
782
891
|
|
783
892
|
if weights
|
784
893
|
command << "WEIGHTS"
|
@@ -796,7 +905,8 @@ class Redis
|
|
796
905
|
end
|
797
906
|
|
798
907
|
def _zsets_operation_store(cmd, destination, keys, weights: nil, aggregate: nil)
|
799
|
-
|
908
|
+
keys.flatten!(1)
|
909
|
+
command = [cmd, destination, keys.size].concat(keys)
|
800
910
|
|
801
911
|
if weights
|
802
912
|
command << "WEIGHTS"
|
@@ -21,15 +21,12 @@ class Redis
|
|
21
21
|
# @return [Array<Hash>] information of the consumers if subcommand is `consumers`
|
22
22
|
def xinfo(subcommand, key, group = nil)
|
23
23
|
args = [:xinfo, subcommand, key, group].compact
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
when 'stream' then Hashify.call(reply)
|
28
|
-
when 'groups', 'consumers' then reply.map { |arr| Hashify.call(arr) }
|
29
|
-
else reply
|
30
|
-
end
|
31
|
-
end
|
24
|
+
block = case subcommand.to_s.downcase
|
25
|
+
when 'stream' then Hashify
|
26
|
+
when 'groups', 'consumers' then proc { |r| r.map(&Hashify) }
|
32
27
|
end
|
28
|
+
|
29
|
+
send_command(args, &block)
|
33
30
|
end
|
34
31
|
|
35
32
|
# Add new entry to the stream.
|
@@ -37,26 +34,35 @@ class Redis
|
|
37
34
|
# @example Without options
|
38
35
|
# redis.xadd('mystream', f1: 'v1', f2: 'v2')
|
39
36
|
# @example With options
|
40
|
-
# redis.xadd('mystream', { f1: 'v1', f2: 'v2' }, id: '0-0', maxlen: 1000, approximate: true)
|
37
|
+
# redis.xadd('mystream', { f1: 'v1', f2: 'v2' }, id: '0-0', maxlen: 1000, approximate: true, nomkstream: true)
|
41
38
|
#
|
42
39
|
# @param key [String] the stream key
|
43
40
|
# @param entry [Hash] one or multiple field-value pairs
|
44
41
|
# @param opts [Hash] several options for `XADD` command
|
45
42
|
#
|
46
43
|
# @option opts [String] :id the entry id, default value is `*`, it means auto generation
|
47
|
-
# @option opts [Integer] :maxlen max length of entries
|
48
|
-
# @option opts [
|
44
|
+
# @option opts [Integer] :maxlen max length of entries to keep
|
45
|
+
# @option opts [Integer] :minid min id of entries to keep
|
46
|
+
# @option opts [Boolean] :approximate whether to add `~` modifier of maxlen/minid or not
|
47
|
+
# @option opts [Boolean] :nomkstream whether to add NOMKSTREAM, default is not to add
|
49
48
|
#
|
50
49
|
# @return [String] the entry id
|
51
|
-
def xadd(key, entry, approximate: nil, maxlen: nil, id: '*')
|
50
|
+
def xadd(key, entry, approximate: nil, maxlen: nil, minid: nil, nomkstream: nil, id: '*')
|
52
51
|
args = [:xadd, key]
|
52
|
+
args << 'NOMKSTREAM' if nomkstream
|
53
53
|
if maxlen
|
54
|
+
raise ArgumentError, "can't supply both maxlen and minid" if minid
|
55
|
+
|
54
56
|
args << "MAXLEN"
|
55
57
|
args << "~" if approximate
|
56
58
|
args << maxlen
|
59
|
+
elsif minid
|
60
|
+
args << "MINID"
|
61
|
+
args << "~" if approximate
|
62
|
+
args << minid
|
57
63
|
end
|
58
64
|
args << id
|
59
|
-
args.concat(entry.
|
65
|
+
args.concat(entry.flatten)
|
60
66
|
send_command(args)
|
61
67
|
end
|
62
68
|
|
@@ -66,14 +72,30 @@ class Redis
|
|
66
72
|
# redis.xtrim('mystream', 1000)
|
67
73
|
# @example With options
|
68
74
|
# redis.xtrim('mystream', 1000, approximate: true)
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
# @
|
75
|
+
# @example With strategy
|
76
|
+
# redis.xtrim('mystream', '1-0', strategy: 'MINID')
|
77
|
+
#
|
78
|
+
# @overload xtrim(key, maxlen, strategy: 'MAXLEN', approximate: true)
|
79
|
+
# @param key [String] the stream key
|
80
|
+
# @param maxlen [Integer] max length of entries
|
81
|
+
# @param strategy [String] the limit strategy, must be MAXLEN
|
82
|
+
# @param approximate [Boolean] whether to add `~` modifier of maxlen or not
|
83
|
+
# @param limit [Integer] maximum count of entries to be evicted
|
84
|
+
# @overload xtrim(key, minid, strategy: 'MINID', approximate: true)
|
85
|
+
# @param key [String] the stream key
|
86
|
+
# @param minid [String] minimum id of entries
|
87
|
+
# @param strategy [String] the limit strategy, must be MINID
|
88
|
+
# @param approximate [Boolean] whether to add `~` modifier of minid or not
|
89
|
+
# @param limit [Integer] maximum count of entries to be evicted
|
73
90
|
#
|
74
91
|
# @return [Integer] the number of entries actually deleted
|
75
|
-
def xtrim(key,
|
76
|
-
|
92
|
+
def xtrim(key, len_or_id, strategy: 'MAXLEN', approximate: false, limit: nil)
|
93
|
+
strategy = strategy.to_s.upcase
|
94
|
+
|
95
|
+
args = [:xtrim, key, strategy]
|
96
|
+
args << '~' if approximate
|
97
|
+
args << len_or_id
|
98
|
+
args.concat(['LIMIT', limit]) if limit
|
77
99
|
send_command(args)
|
78
100
|
end
|
79
101
|
|
@@ -113,7 +135,7 @@ class Redis
|
|
113
135
|
def xrange(key, start = '-', range_end = '+', count: nil)
|
114
136
|
args = [:xrange, key, start, range_end]
|
115
137
|
args.concat(['COUNT', count]) if count
|
116
|
-
|
138
|
+
send_command(args, &HashifyStreamEntries)
|
117
139
|
end
|
118
140
|
|
119
141
|
# Fetches entries of the stream in descending order.
|
@@ -334,6 +356,8 @@ class Redis
|
|
334
356
|
# redis.xpending('mystream', 'mygroup')
|
335
357
|
# @example With range options
|
336
358
|
# redis.xpending('mystream', 'mygroup', '-', '+', 10)
|
359
|
+
# @example With range and idle time options
|
360
|
+
# redis.xpending('mystream', 'mygroup', '-', '+', 10, idle: 9000)
|
337
361
|
# @example With range and consumer options
|
338
362
|
# redis.xpending('mystream', 'mygroup', '-', '+', 10, 'consumer1')
|
339
363
|
#
|
@@ -344,10 +368,13 @@ class Redis
|
|
344
368
|
# @param count [Integer] count the number of entries as limit
|
345
369
|
# @param consumer [String] the consumer name
|
346
370
|
#
|
371
|
+
# @option opts [Integer] :idle pending message minimum idle time in milliseconds
|
372
|
+
#
|
347
373
|
# @return [Hash] the summary of pending entries
|
348
374
|
# @return [Array<Hash>] the pending entries details if options were specified
|
349
|
-
def xpending(key, group, *args)
|
375
|
+
def xpending(key, group, *args, idle: nil)
|
350
376
|
command_args = [:xpending, key, group]
|
377
|
+
command_args << 'IDLE' << Integer(idle) if idle
|
351
378
|
case args.size
|
352
379
|
when 0, 3, 4
|
353
380
|
command_args.concat(args)
|