redis 4.8.1 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +75 -0
- data/README.md +124 -161
- data/lib/redis/client.rb +82 -616
- 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 +27 -23
- data/lib/redis/commands/lists.rb +74 -25
- data/lib/redis/commands/pubsub.rb +34 -25
- data/lib/redis/commands/server.rb +15 -15
- data/lib/redis/commands/sets.rb +35 -40
- data/lib/redis/commands/sorted_sets.rb +88 -12
- data/lib/redis/commands/streams.rb +39 -19
- data/lib/redis/commands/strings.rb +18 -17
- data/lib/redis/commands/transactions.rb +7 -31
- data/lib/redis/commands.rb +4 -7
- data/lib/redis/distributed.rb +132 -68
- 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 +77 -184
- metadata +10 -54
- 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 -68
- 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
data/lib/redis/commands/sets.rb
CHANGED
@@ -15,56 +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
|
-
def sadd(key, member)
|
23
|
-
block = if Redis.sadd_returns_boolean && !member.is_a?(Array)
|
24
|
-
::Redis.deprecate!(
|
25
|
-
"Redis#sadd will always return an Integer in Redis 5.0.0. Use Redis#sadd? instead." \
|
26
|
-
"(called from: #{caller(1, 1).first})"
|
27
|
-
)
|
28
|
-
Boolify
|
29
|
-
end
|
30
|
-
send_command([:sadd, key, member], &block)
|
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))
|
31
22
|
end
|
32
23
|
|
33
24
|
# Add one or more members to a set.
|
34
25
|
#
|
35
26
|
# @param [String] key
|
36
27
|
# @param [String, Array<String>] member one member, or array of members
|
37
|
-
# @return [Boolean]
|
38
|
-
def sadd?(key,
|
39
|
-
|
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)
|
40
32
|
end
|
41
33
|
|
42
34
|
# Remove one or more members from a set.
|
43
35
|
#
|
44
36
|
# @param [String] key
|
45
37
|
# @param [String, Array<String>] member one member, or array of members
|
46
|
-
# @return [
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
def srem(key, member)
|
51
|
-
block = if Redis.sadd_returns_boolean && !member.is_a?(Array)
|
52
|
-
::Redis.deprecate!(
|
53
|
-
"Redis#srem will always return an Integer in Redis 5.0.0. Use Redis#srem? instead." \
|
54
|
-
"(called from: #{caller(1, 1).first})"
|
55
|
-
)
|
56
|
-
Boolify
|
57
|
-
end
|
58
|
-
send_command([:srem, key, member], &block)
|
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))
|
59
42
|
end
|
60
43
|
|
61
44
|
# Remove one or more members from a set.
|
62
45
|
#
|
63
46
|
# @param [String] key
|
64
47
|
# @param [String, Array<String>] member one member, or array of members
|
65
|
-
# @return [Boolean]
|
66
|
-
def srem?(key,
|
67
|
-
|
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)
|
68
52
|
end
|
69
53
|
|
70
54
|
# Remove and return one or more random member from a set.
|
@@ -76,7 +60,7 @@ class Redis
|
|
76
60
|
if count.nil?
|
77
61
|
send_command([:spop, key])
|
78
62
|
else
|
79
|
-
send_command([:spop, key, count])
|
63
|
+
send_command([:spop, key, Integer(count)])
|
80
64
|
end
|
81
65
|
end
|
82
66
|
|
@@ -118,7 +102,8 @@ class Redis
|
|
118
102
|
# @param [String, Array<String>] members
|
119
103
|
# @return [Array<Boolean>]
|
120
104
|
def smismember(key, *members)
|
121
|
-
|
105
|
+
members.flatten!(1)
|
106
|
+
send_command([:smismember, key].concat(members)) do |reply|
|
122
107
|
reply.map(&Boolify)
|
123
108
|
end
|
124
109
|
end
|
@@ -136,7 +121,8 @@ class Redis
|
|
136
121
|
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
137
122
|
# @return [Array<String>] members in the difference
|
138
123
|
def sdiff(*keys)
|
139
|
-
|
124
|
+
keys.flatten!(1)
|
125
|
+
send_command([:sdiff].concat(keys))
|
140
126
|
end
|
141
127
|
|
142
128
|
# Subtract multiple sets and store the resulting set in a key.
|
@@ -145,7 +131,8 @@ class Redis
|
|
145
131
|
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
146
132
|
# @return [Integer] number of elements in the resulting set
|
147
133
|
def sdiffstore(destination, *keys)
|
148
|
-
|
134
|
+
keys.flatten!(1)
|
135
|
+
send_command([:sdiffstore, destination].concat(keys))
|
149
136
|
end
|
150
137
|
|
151
138
|
# Intersect multiple sets.
|
@@ -153,7 +140,8 @@ class Redis
|
|
153
140
|
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
154
141
|
# @return [Array<String>] members in the intersection
|
155
142
|
def sinter(*keys)
|
156
|
-
|
143
|
+
keys.flatten!(1)
|
144
|
+
send_command([:sinter].concat(keys))
|
157
145
|
end
|
158
146
|
|
159
147
|
# Intersect multiple sets and store the resulting set in a key.
|
@@ -162,7 +150,8 @@ class Redis
|
|
162
150
|
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
163
151
|
# @return [Integer] number of elements in the resulting set
|
164
152
|
def sinterstore(destination, *keys)
|
165
|
-
|
153
|
+
keys.flatten!(1)
|
154
|
+
send_command([:sinterstore, destination].concat(keys))
|
166
155
|
end
|
167
156
|
|
168
157
|
# Add multiple sets.
|
@@ -170,7 +159,8 @@ class Redis
|
|
170
159
|
# @param [String, Array<String>] keys keys pointing to sets to unify
|
171
160
|
# @return [Array<String>] members in the union
|
172
161
|
def sunion(*keys)
|
173
|
-
|
162
|
+
keys.flatten!(1)
|
163
|
+
send_command([:sunion].concat(keys))
|
174
164
|
end
|
175
165
|
|
176
166
|
# Add multiple sets and store the resulting set in a key.
|
@@ -179,7 +169,8 @@ class Redis
|
|
179
169
|
# @param [String, Array<String>] keys keys pointing to sets to unify
|
180
170
|
# @return [Integer] number of elements in the resulting set
|
181
171
|
def sunionstore(destination, *keys)
|
182
|
-
|
172
|
+
keys.flatten!(1)
|
173
|
+
send_command([:sunionstore, destination].concat(keys))
|
183
174
|
end
|
184
175
|
|
185
176
|
# Scan a set
|
@@ -193,6 +184,8 @@ class Redis
|
|
193
184
|
# - `:count => Integer`: return count keys at most per iteration
|
194
185
|
#
|
195
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
|
196
189
|
def sscan(key, cursor, **options)
|
197
190
|
_scan(:sscan, cursor, [key], **options)
|
198
191
|
end
|
@@ -208,6 +201,8 @@ class Redis
|
|
208
201
|
# - `:count => Integer`: return count keys at most per iteration
|
209
202
|
#
|
210
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
|
211
206
|
def sscan_each(key, **options, &block)
|
212
207
|
return to_enum(:sscan_each, key, **options) unless block_given?
|
213
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"
|
@@ -466,7 +536,7 @@ class Redis
|
|
466
536
|
|
467
537
|
if limit
|
468
538
|
args << "LIMIT"
|
469
|
-
args.concat(limit)
|
539
|
+
args.concat(limit.map { |l| Integer(l) })
|
470
540
|
end
|
471
541
|
|
472
542
|
send_command(args)
|
@@ -488,7 +558,7 @@ class Redis
|
|
488
558
|
|
489
559
|
if limit
|
490
560
|
args << "LIMIT"
|
491
|
-
args.concat(limit)
|
561
|
+
args.concat(limit.map { |l| Integer(l) })
|
492
562
|
end
|
493
563
|
|
494
564
|
send_command(args)
|
@@ -531,7 +601,7 @@ class Redis
|
|
531
601
|
|
532
602
|
if limit
|
533
603
|
args << "LIMIT"
|
534
|
-
args.concat(limit)
|
604
|
+
args.concat(limit.map { |l| Integer(l) })
|
535
605
|
end
|
536
606
|
|
537
607
|
send_command(args, &block)
|
@@ -561,7 +631,7 @@ class Redis
|
|
561
631
|
|
562
632
|
if limit
|
563
633
|
args << "LIMIT"
|
564
|
-
args.concat(limit)
|
634
|
+
args.concat(limit.map { |l| Integer(l) })
|
565
635
|
end
|
566
636
|
|
567
637
|
send_command(args, &block)
|
@@ -747,6 +817,8 @@ class Redis
|
|
747
817
|
#
|
748
818
|
# @return [String, Array<[String, Float]>] the next cursor and all found
|
749
819
|
# members and scores
|
820
|
+
#
|
821
|
+
# See the [Redis Server ZSCAN documentation](https://redis.io/docs/latest/commands/zscan/) for further details
|
750
822
|
def zscan(key, cursor, **options)
|
751
823
|
_scan(:zscan, cursor, [key], **options) do |reply|
|
752
824
|
[reply[0], FloatifyPairs.call(reply[1])]
|
@@ -764,6 +836,8 @@ class Redis
|
|
764
836
|
# - `:count => Integer`: return count keys at most per iteration
|
765
837
|
#
|
766
838
|
# @return [Enumerator] an enumerator for all found scores and members
|
839
|
+
#
|
840
|
+
# See the [Redis Server ZSCAN documentation](https://redis.io/docs/latest/commands/zscan/) for further details
|
767
841
|
def zscan_each(key, **options, &block)
|
768
842
|
return to_enum(:zscan_each, key, **options) unless block_given?
|
769
843
|
|
@@ -778,7 +852,8 @@ class Redis
|
|
778
852
|
private
|
779
853
|
|
780
854
|
def _zsets_operation(cmd, *keys, weights: nil, aggregate: nil, with_scores: false)
|
781
|
-
|
855
|
+
keys.flatten!(1)
|
856
|
+
command = [cmd, keys.size].concat(keys)
|
782
857
|
|
783
858
|
if weights
|
784
859
|
command << "WEIGHTS"
|
@@ -796,7 +871,8 @@ class Redis
|
|
796
871
|
end
|
797
872
|
|
798
873
|
def _zsets_operation_store(cmd, destination, keys, weights: nil, aggregate: nil)
|
799
|
-
|
874
|
+
keys.flatten!(1)
|
875
|
+
command = [cmd, destination, keys.size].concat(keys)
|
800
876
|
|
801
877
|
if weights
|
802
878
|
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,7 +34,7 @@ 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
|
@@ -46,17 +43,19 @@ class Redis
|
|
46
43
|
# @option opts [String] :id the entry id, default value is `*`, it means auto generation
|
47
44
|
# @option opts [Integer] :maxlen max length of entries
|
48
45
|
# @option opts [Boolean] :approximate whether to add `~` modifier of maxlen or not
|
46
|
+
# @option opts [Boolean] :nomkstream whether to add NOMKSTREAM, default is not to add
|
49
47
|
#
|
50
48
|
# @return [String] the entry id
|
51
|
-
def xadd(key, entry, approximate: nil, maxlen: nil, id: '*')
|
49
|
+
def xadd(key, entry, approximate: nil, maxlen: nil, nomkstream: nil, id: '*')
|
52
50
|
args = [:xadd, key]
|
51
|
+
args << 'NOMKSTREAM' if nomkstream
|
53
52
|
if maxlen
|
54
53
|
args << "MAXLEN"
|
55
54
|
args << "~" if approximate
|
56
55
|
args << maxlen
|
57
56
|
end
|
58
57
|
args << id
|
59
|
-
args.concat(entry.
|
58
|
+
args.concat(entry.flatten)
|
60
59
|
send_command(args)
|
61
60
|
end
|
62
61
|
|
@@ -66,14 +65,30 @@ class Redis
|
|
66
65
|
# redis.xtrim('mystream', 1000)
|
67
66
|
# @example With options
|
68
67
|
# redis.xtrim('mystream', 1000, approximate: true)
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
# @
|
68
|
+
# @example With strategy
|
69
|
+
# redis.xtrim('mystream', '1-0', strategy: 'MINID')
|
70
|
+
#
|
71
|
+
# @overload xtrim(key, maxlen, strategy: 'MAXLEN', approximate: true)
|
72
|
+
# @param key [String] the stream key
|
73
|
+
# @param maxlen [Integer] max length of entries
|
74
|
+
# @param strategy [String] the limit strategy, must be MAXLEN
|
75
|
+
# @param approximate [Boolean] whether to add `~` modifier of maxlen or not
|
76
|
+
# @param limit [Integer] maximum count of entries to be evicted
|
77
|
+
# @overload xtrim(key, minid, strategy: 'MINID', approximate: true)
|
78
|
+
# @param key [String] the stream key
|
79
|
+
# @param minid [String] minimum id of entries
|
80
|
+
# @param strategy [String] the limit strategy, must be MINID
|
81
|
+
# @param approximate [Boolean] whether to add `~` modifier of minid or not
|
82
|
+
# @param limit [Integer] maximum count of entries to be evicted
|
73
83
|
#
|
74
84
|
# @return [Integer] the number of entries actually deleted
|
75
|
-
def xtrim(key,
|
76
|
-
|
85
|
+
def xtrim(key, len_or_id, strategy: 'MAXLEN', approximate: false, limit: nil)
|
86
|
+
strategy = strategy.to_s.upcase
|
87
|
+
|
88
|
+
args = [:xtrim, key, strategy]
|
89
|
+
args << '~' if approximate
|
90
|
+
args << len_or_id
|
91
|
+
args.concat(['LIMIT', limit]) if limit
|
77
92
|
send_command(args)
|
78
93
|
end
|
79
94
|
|
@@ -113,7 +128,7 @@ class Redis
|
|
113
128
|
def xrange(key, start = '-', range_end = '+', count: nil)
|
114
129
|
args = [:xrange, key, start, range_end]
|
115
130
|
args.concat(['COUNT', count]) if count
|
116
|
-
|
131
|
+
send_command(args, &HashifyStreamEntries)
|
117
132
|
end
|
118
133
|
|
119
134
|
# Fetches entries of the stream in descending order.
|
@@ -334,6 +349,8 @@ class Redis
|
|
334
349
|
# redis.xpending('mystream', 'mygroup')
|
335
350
|
# @example With range options
|
336
351
|
# redis.xpending('mystream', 'mygroup', '-', '+', 10)
|
352
|
+
# @example With range and idle time options
|
353
|
+
# redis.xpending('mystream', 'mygroup', '-', '+', 10, idle: 9000)
|
337
354
|
# @example With range and consumer options
|
338
355
|
# redis.xpending('mystream', 'mygroup', '-', '+', 10, 'consumer1')
|
339
356
|
#
|
@@ -344,10 +361,13 @@ class Redis
|
|
344
361
|
# @param count [Integer] count the number of entries as limit
|
345
362
|
# @param consumer [String] the consumer name
|
346
363
|
#
|
364
|
+
# @option opts [Integer] :idle pending message minimum idle time in milliseconds
|
365
|
+
#
|
347
366
|
# @return [Hash] the summary of pending entries
|
348
367
|
# @return [Array<Hash>] the pending entries details if options were specified
|
349
|
-
def xpending(key, group, *args)
|
368
|
+
def xpending(key, group, *args, idle: nil)
|
350
369
|
command_args = [:xpending, key, group]
|
370
|
+
command_args << 'IDLE' << Integer(idle) if idle
|
351
371
|
case args.size
|
352
372
|
when 0, 3, 4
|
353
373
|
command_args.concat(args)
|
@@ -25,7 +25,7 @@ class Redis
|
|
25
25
|
# @param [Integer] decrement
|
26
26
|
# @return [Integer] value after decrementing it
|
27
27
|
def decrby(key, decrement)
|
28
|
-
send_command([:decrby, key, decrement])
|
28
|
+
send_command([:decrby, key, Integer(decrement)])
|
29
29
|
end
|
30
30
|
|
31
31
|
# Increment the integer value of a key by one.
|
@@ -50,7 +50,7 @@ class Redis
|
|
50
50
|
# @param [Integer] increment
|
51
51
|
# @return [Integer] value after incrementing it
|
52
52
|
def incrby(key, increment)
|
53
|
-
send_command([:incrby, key, increment])
|
53
|
+
send_command([:incrby, key, Integer(increment)])
|
54
54
|
end
|
55
55
|
|
56
56
|
# Increment the numeric value of a key by the given float number.
|
@@ -63,7 +63,7 @@ class Redis
|
|
63
63
|
# @param [Float] increment
|
64
64
|
# @return [Float] value after incrementing it
|
65
65
|
def incrbyfloat(key, increment)
|
66
|
-
send_command([:incrbyfloat, key, increment], &Floatify)
|
66
|
+
send_command([:incrbyfloat, key, Float(increment)], &Floatify)
|
67
67
|
end
|
68
68
|
|
69
69
|
# Set the string value of a key.
|
@@ -82,10 +82,10 @@ class Redis
|
|
82
82
|
# @return [String, Boolean] `"OK"` or true, false if `:nx => true` or `:xx => true`
|
83
83
|
def set(key, value, ex: nil, px: nil, exat: nil, pxat: nil, nx: nil, xx: nil, keepttl: nil, get: nil)
|
84
84
|
args = [:set, key, value.to_s]
|
85
|
-
args << "EX" << ex if ex
|
86
|
-
args << "PX" << px if px
|
87
|
-
args << "EXAT" << exat if exat
|
88
|
-
args << "PXAT" << pxat if pxat
|
85
|
+
args << "EX" << Integer(ex) if ex
|
86
|
+
args << "PX" << Integer(px) if px
|
87
|
+
args << "EXAT" << Integer(exat) if exat
|
88
|
+
args << "PXAT" << Integer(pxat) if pxat
|
89
89
|
args << "NX" if nx
|
90
90
|
args << "XX" if xx
|
91
91
|
args << "KEEPTTL" if keepttl
|
@@ -105,7 +105,7 @@ class Redis
|
|
105
105
|
# @param [String] value
|
106
106
|
# @return [String] `"OK"`
|
107
107
|
def setex(key, ttl, value)
|
108
|
-
send_command([:setex, key, ttl, value.to_s])
|
108
|
+
send_command([:setex, key, Integer(ttl), value.to_s])
|
109
109
|
end
|
110
110
|
|
111
111
|
# Set the time to live in milliseconds of a key.
|
@@ -115,7 +115,7 @@ class Redis
|
|
115
115
|
# @param [String] value
|
116
116
|
# @return [String] `"OK"`
|
117
117
|
def psetex(key, ttl, value)
|
118
|
-
send_command([:psetex, key, ttl, value.to_s])
|
118
|
+
send_command([:psetex, key, Integer(ttl), value.to_s])
|
119
119
|
end
|
120
120
|
|
121
121
|
# Set the value of a key, only if the key does not exist.
|
@@ -152,7 +152,7 @@ class Redis
|
|
152
152
|
#
|
153
153
|
# @see #mset
|
154
154
|
def mapped_mset(hash)
|
155
|
-
mset(hash.
|
155
|
+
mset(hash.flatten)
|
156
156
|
end
|
157
157
|
|
158
158
|
# Set one or more values, only if none of the keys exist.
|
@@ -180,7 +180,7 @@ class Redis
|
|
180
180
|
#
|
181
181
|
# @see #msetnx
|
182
182
|
def mapped_msetnx(hash)
|
183
|
-
msetnx(hash.
|
183
|
+
msetnx(hash.flatten)
|
184
184
|
end
|
185
185
|
|
186
186
|
# Get the value of a key.
|
@@ -202,6 +202,7 @@ class Redis
|
|
202
202
|
#
|
203
203
|
# @see #mapped_mget
|
204
204
|
def mget(*keys, &blk)
|
205
|
+
keys.flatten!(1)
|
205
206
|
send_command([:mget, *keys], &blk)
|
206
207
|
end
|
207
208
|
|
@@ -232,7 +233,7 @@ class Redis
|
|
232
233
|
# @param [String] value
|
233
234
|
# @return [Integer] length of the string after it was modified
|
234
235
|
def setrange(key, offset, value)
|
235
|
-
send_command([:setrange, key, offset, value.to_s])
|
236
|
+
send_command([:setrange, key, Integer(offset), value.to_s])
|
236
237
|
end
|
237
238
|
|
238
239
|
# Get a substring of the string stored at a key.
|
@@ -243,7 +244,7 @@ class Redis
|
|
243
244
|
# the end of the string
|
244
245
|
# @return [Integer] `0` or `1`
|
245
246
|
def getrange(key, start, stop)
|
246
|
-
send_command([:getrange, key, start, stop])
|
247
|
+
send_command([:getrange, key, Integer(start), Integer(stop)])
|
247
248
|
end
|
248
249
|
|
249
250
|
# Append a value to a key.
|
@@ -291,10 +292,10 @@ class Redis
|
|
291
292
|
# @return [String] The value of key, or nil when key does not exist.
|
292
293
|
def getex(key, ex: nil, px: nil, exat: nil, pxat: nil, persist: false)
|
293
294
|
args = [:getex, key]
|
294
|
-
args << "EX" << ex if ex
|
295
|
-
args << "PX" << px if px
|
296
|
-
args << "EXAT" << exat if exat
|
297
|
-
args << "PXAT" << pxat if pxat
|
295
|
+
args << "EX" << Integer(ex) if ex
|
296
|
+
args << "PX" << Integer(px) if px
|
297
|
+
args << "EXAT" << Integer(exat) if exat
|
298
|
+
args << "PXAT" << Integer(pxat) if pxat
|
298
299
|
args << "PERSIST" if persist
|
299
300
|
|
300
301
|
send_command(args)
|
@@ -5,48 +5,26 @@ class Redis
|
|
5
5
|
module Transactions
|
6
6
|
# Mark the start of a transaction block.
|
7
7
|
#
|
8
|
-
# Passing a block is optional.
|
9
|
-
#
|
10
8
|
# @example With a block
|
11
9
|
# redis.multi do |multi|
|
12
10
|
# multi.set("key", "value")
|
13
11
|
# multi.incr("counter")
|
14
12
|
# end # => ["OK", 6]
|
15
13
|
#
|
16
|
-
# @example Without a block
|
17
|
-
# redis.multi
|
18
|
-
# # => "OK"
|
19
|
-
# redis.set("key", "value")
|
20
|
-
# # => "QUEUED"
|
21
|
-
# redis.incr("counter")
|
22
|
-
# # => "QUEUED"
|
23
|
-
# redis.exec
|
24
|
-
# # => ["OK", 6]
|
25
|
-
#
|
26
14
|
# @yield [multi] the commands that are called inside this block are cached
|
27
15
|
# and written to the server upon returning from it
|
28
16
|
# @yieldparam [Redis] multi `self`
|
29
17
|
#
|
30
|
-
# @return [
|
31
|
-
# -
|
32
|
-
# - when a block is given, an array with replies
|
18
|
+
# @return [Array<...>]
|
19
|
+
# - an array with replies
|
33
20
|
#
|
34
21
|
# @see #watch
|
35
22
|
# @see #unwatch
|
36
|
-
def multi
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
synchronize do |prior_client|
|
43
|
-
pipeline = Pipeline::Multi.new(prior_client)
|
44
|
-
pipelined_connection = PipelinedConnection.new(pipeline)
|
45
|
-
yield pipelined_connection
|
46
|
-
prior_client.call_pipeline(pipeline)
|
23
|
+
def multi
|
24
|
+
synchronize do |client|
|
25
|
+
client.multi do |raw_transaction|
|
26
|
+
yield MultiConnection.new(raw_transaction)
|
47
27
|
end
|
48
|
-
else
|
49
|
-
send_command([:multi])
|
50
28
|
end
|
51
29
|
end
|
52
30
|
|
@@ -82,7 +60,7 @@ class Redis
|
|
82
60
|
# @see #multi
|
83
61
|
def watch(*keys)
|
84
62
|
synchronize do |client|
|
85
|
-
res = client.
|
63
|
+
res = client.call_v([:watch] + keys)
|
86
64
|
|
87
65
|
if block_given?
|
88
66
|
begin
|
@@ -125,8 +103,6 @@ class Redis
|
|
125
103
|
|
126
104
|
# Discard all commands issued after MULTI.
|
127
105
|
#
|
128
|
-
# Only call this method when `#multi` was called **without** a block.
|
129
|
-
#
|
130
106
|
# @return [String] `"OK"`
|
131
107
|
#
|
132
108
|
# @see #multi
|