redis 4.6.0 → 5.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +70 -1
- data/README.md +75 -146
- data/lib/redis/client.rb +77 -616
- data/lib/redis/commands/bitmaps.rb +4 -1
- 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 +9 -6
- data/lib/redis/commands/hyper_log_log.rb +1 -1
- data/lib/redis/commands/keys.rb +53 -27
- data/lib/redis/commands/lists.rb +19 -23
- data/lib/redis/commands/pubsub.rb +7 -25
- data/lib/redis/commands/server.rb +15 -15
- data/lib/redis/commands/sets.rb +43 -36
- data/lib/redis/commands/sorted_sets.rb +27 -13
- data/lib/redis/commands/streams.rb +39 -19
- data/lib/redis/commands/strings.rb +18 -17
- data/lib/redis/commands/transactions.rb +26 -3
- data/lib/redis/commands.rb +4 -9
- data/lib/redis/distributed.rb +100 -67
- data/lib/redis/errors.rb +15 -41
- data/lib/redis/hash_ring.rb +26 -26
- data/lib/redis/pipeline.rb +56 -203
- data/lib/redis/subscribe.rb +23 -15
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +90 -178
- metadata +9 -53
- 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 -37
- data/lib/redis/cluster/option.rb +0 -93
- data/lib/redis/cluster/slot.rb +0 -86
- data/lib/redis/cluster/slot_loader.rb +0 -49
- 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 -431
- data/lib/redis/connection/synchrony.rb +0 -148
- data/lib/redis/connection.rb +0 -11
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
|
@@ -60,8 +60,11 @@ class Redis
|
|
60
60
|
command << "INCR" if incr
|
61
61
|
|
62
62
|
if args.size == 1 && args[0].is_a?(Array)
|
63
|
+
members_to_add = args[0]
|
64
|
+
return 0 if members_to_add.empty?
|
65
|
+
|
63
66
|
# Variadic: return float if INCR, integer if !INCR
|
64
|
-
send_command(command +
|
67
|
+
send_command(command + members_to_add, &(incr ? Floatify : nil))
|
65
68
|
elsif args.size == 2
|
66
69
|
# Single pair: return float if INCR, boolean if !INCR
|
67
70
|
send_command(command + args, &(incr ? Floatify : Boolify))
|
@@ -102,6 +105,11 @@ class Redis
|
|
102
105
|
# - `Integer` when an array of pairs is specified, holding the number of
|
103
106
|
# members that were removed to the sorted set
|
104
107
|
def zrem(key, member)
|
108
|
+
if member.is_a?(Array)
|
109
|
+
members_to_remove = member
|
110
|
+
return 0 if members_to_remove.empty?
|
111
|
+
end
|
112
|
+
|
105
113
|
send_command([:zrem, key, member]) do |reply|
|
106
114
|
if member.is_a? Array
|
107
115
|
# Variadic: return integer
|
@@ -128,7 +136,9 @@ class Redis
|
|
128
136
|
# @return [Array<String, Float>] element and score pair if count is not specified
|
129
137
|
# @return [Array<Array<String, Float>>] list of popped elements and scores
|
130
138
|
def zpopmax(key, count = nil)
|
131
|
-
|
139
|
+
command = [:zpopmax, key]
|
140
|
+
command << Integer(count) if count
|
141
|
+
send_command(command) do |members|
|
132
142
|
members = FloatifyPairs.call(members)
|
133
143
|
count.to_i > 1 ? members : members.first
|
134
144
|
end
|
@@ -149,7 +159,9 @@ class Redis
|
|
149
159
|
# @return [Array<String, Float>] element and score pair if count is not specified
|
150
160
|
# @return [Array<Array<String, Float>>] list of popped elements and scores
|
151
161
|
def zpopmin(key, count = nil)
|
152
|
-
|
162
|
+
command = [:zpopmin, key]
|
163
|
+
command << Integer(count) if count
|
164
|
+
send_command(command) do |members|
|
153
165
|
members = FloatifyPairs.call(members)
|
154
166
|
count.to_i > 1 ? members : members.first
|
155
167
|
end
|
@@ -253,7 +265,7 @@ class Redis
|
|
253
265
|
end
|
254
266
|
|
255
267
|
args = [:zrandmember, key]
|
256
|
-
args << count if count
|
268
|
+
args << Integer(count) if count
|
257
269
|
|
258
270
|
if with_scores
|
259
271
|
args << "WITHSCORES"
|
@@ -305,7 +317,7 @@ class Redis
|
|
305
317
|
|
306
318
|
if limit
|
307
319
|
args << "LIMIT"
|
308
|
-
args.concat(limit)
|
320
|
+
args.concat(limit.map { |l| Integer(l) })
|
309
321
|
end
|
310
322
|
|
311
323
|
if with_scores
|
@@ -346,7 +358,7 @@ class Redis
|
|
346
358
|
|
347
359
|
if limit
|
348
360
|
args << "LIMIT"
|
349
|
-
args.concat(limit)
|
361
|
+
args.concat(limit.map { |l| Integer(l) })
|
350
362
|
end
|
351
363
|
|
352
364
|
send_command(args)
|
@@ -364,7 +376,7 @@ class Redis
|
|
364
376
|
#
|
365
377
|
# @see #zrange
|
366
378
|
def zrevrange(key, start, stop, withscores: false, with_scores: withscores)
|
367
|
-
args = [:zrevrange, key, start, stop]
|
379
|
+
args = [:zrevrange, key, Integer(start), Integer(stop)]
|
368
380
|
|
369
381
|
if with_scores
|
370
382
|
args << "WITHSCORES"
|
@@ -458,7 +470,7 @@ class Redis
|
|
458
470
|
|
459
471
|
if limit
|
460
472
|
args << "LIMIT"
|
461
|
-
args.concat(limit)
|
473
|
+
args.concat(limit.map { |l| Integer(l) })
|
462
474
|
end
|
463
475
|
|
464
476
|
send_command(args)
|
@@ -480,7 +492,7 @@ class Redis
|
|
480
492
|
|
481
493
|
if limit
|
482
494
|
args << "LIMIT"
|
483
|
-
args.concat(limit)
|
495
|
+
args.concat(limit.map { |l| Integer(l) })
|
484
496
|
end
|
485
497
|
|
486
498
|
send_command(args)
|
@@ -523,7 +535,7 @@ class Redis
|
|
523
535
|
|
524
536
|
if limit
|
525
537
|
args << "LIMIT"
|
526
|
-
args.concat(limit)
|
538
|
+
args.concat(limit.map { |l| Integer(l) })
|
527
539
|
end
|
528
540
|
|
529
541
|
send_command(args, &block)
|
@@ -553,7 +565,7 @@ class Redis
|
|
553
565
|
|
554
566
|
if limit
|
555
567
|
args << "LIMIT"
|
556
|
-
args.concat(limit)
|
568
|
+
args.concat(limit.map { |l| Integer(l) })
|
557
569
|
end
|
558
570
|
|
559
571
|
send_command(args, &block)
|
@@ -770,7 +782,8 @@ class Redis
|
|
770
782
|
private
|
771
783
|
|
772
784
|
def _zsets_operation(cmd, *keys, weights: nil, aggregate: nil, with_scores: false)
|
773
|
-
|
785
|
+
keys.flatten!(1)
|
786
|
+
command = [cmd, keys.size].concat(keys)
|
774
787
|
|
775
788
|
if weights
|
776
789
|
command << "WEIGHTS"
|
@@ -788,7 +801,8 @@ class Redis
|
|
788
801
|
end
|
789
802
|
|
790
803
|
def _zsets_operation_store(cmd, destination, keys, weights: nil, aggregate: nil)
|
791
|
-
|
804
|
+
keys.flatten!(1)
|
805
|
+
command = [cmd, destination, keys.size].concat(keys)
|
792
806
|
|
793
807
|
if weights
|
794
808
|
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)
|
@@ -3,6 +3,31 @@
|
|
3
3
|
class Redis
|
4
4
|
module Commands
|
5
5
|
module Transactions
|
6
|
+
# Mark the start of a transaction block.
|
7
|
+
#
|
8
|
+
# @example With a block
|
9
|
+
# redis.multi do |multi|
|
10
|
+
# multi.set("key", "value")
|
11
|
+
# multi.incr("counter")
|
12
|
+
# end # => ["OK", 6]
|
13
|
+
#
|
14
|
+
# @yield [multi] the commands that are called inside this block are cached
|
15
|
+
# and written to the server upon returning from it
|
16
|
+
# @yieldparam [Redis] multi `self`
|
17
|
+
#
|
18
|
+
# @return [Array<...>]
|
19
|
+
# - an array with replies
|
20
|
+
#
|
21
|
+
# @see #watch
|
22
|
+
# @see #unwatch
|
23
|
+
def multi
|
24
|
+
synchronize do |client|
|
25
|
+
client.multi do |raw_transaction|
|
26
|
+
yield MultiConnection.new(raw_transaction)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
6
31
|
# Watch the given keys to determine execution of the MULTI/EXEC block.
|
7
32
|
#
|
8
33
|
# Using a block is optional, but is necessary for thread-safety.
|
@@ -35,7 +60,7 @@ class Redis
|
|
35
60
|
# @see #multi
|
36
61
|
def watch(*keys)
|
37
62
|
synchronize do |client|
|
38
|
-
res = client.
|
63
|
+
res = client.call_v([:watch] + keys)
|
39
64
|
|
40
65
|
if block_given?
|
41
66
|
begin
|
@@ -78,8 +103,6 @@ class Redis
|
|
78
103
|
|
79
104
|
# Discard all commands issued after MULTI.
|
80
105
|
#
|
81
|
-
# Only call this method when `#multi` was called **without** a block.
|
82
|
-
#
|
83
106
|
# @return [String] `"OK"`
|
84
107
|
#
|
85
108
|
# @see #multi
|
data/lib/redis/commands.rb
CHANGED
@@ -40,14 +40,7 @@ class Redis
|
|
40
40
|
# where the method call will return nil. Propagate the nil instead of falsely
|
41
41
|
# returning false.
|
42
42
|
Boolify = lambda { |value|
|
43
|
-
|
44
|
-
when 1
|
45
|
-
true
|
46
|
-
when 0
|
47
|
-
false
|
48
|
-
else
|
49
|
-
value
|
50
|
-
end
|
43
|
+
value != 0 unless value.nil?
|
51
44
|
}
|
52
45
|
|
53
46
|
BoolifySet = lambda { |value|
|
@@ -126,7 +119,9 @@ class Redis
|
|
126
119
|
HashifyStreamAutoclaim = lambda { |reply|
|
127
120
|
{
|
128
121
|
'next' => reply[0],
|
129
|
-
'entries' => reply[1].map
|
122
|
+
'entries' => reply[1].compact.map do |entry, values|
|
123
|
+
[entry, values.each_slice(2)&.to_h]
|
124
|
+
end
|
130
125
|
}
|
131
126
|
}
|
132
127
|
|