redis 4.8.1 → 6.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 +4 -4
- data/CHANGELOG.md +138 -1
- data/README.md +285 -169
- data/lib/redis/client.rb +116 -611
- 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 +109 -7
- data/lib/redis/commands/hashes.rb +179 -8
- data/lib/redis/commands/hyper_log_log.rb +1 -1
- data/lib/redis/commands/keys.rb +32 -24
- data/lib/redis/commands/lists.rb +167 -25
- data/lib/redis/commands/modules/json.rb +530 -0
- data/lib/redis/commands/modules/search/aggregation.rb +418 -0
- data/lib/redis/commands/modules/search/dialect.rb +14 -0
- data/lib/redis/commands/modules/search/field.rb +306 -0
- data/lib/redis/commands/modules/search/hybrid.rb +359 -0
- data/lib/redis/commands/modules/search/index.rb +351 -0
- data/lib/redis/commands/modules/search/index_definition.rb +114 -0
- data/lib/redis/commands/modules/search/miscellaneous.rb +607 -0
- data/lib/redis/commands/modules/search/query.rb +738 -0
- data/lib/redis/commands/modules/search/result.rb +488 -0
- data/lib/redis/commands/modules/search/schema.rb +211 -0
- data/lib/redis/commands/modules/search.rb +19 -0
- data/lib/redis/commands/pubsub.rb +34 -25
- data/lib/redis/commands/server.rb +15 -15
- data/lib/redis/commands/sets.rb +76 -40
- data/lib/redis/commands/sorted_sets.rb +128 -19
- data/lib/redis/commands/streams.rb +75 -28
- data/lib/redis/commands/strings.rb +18 -17
- data/lib/redis/commands/transactions.rb +7 -31
- data/lib/redis/commands.rb +39 -20
- data/lib/redis/distributed.rb +407 -73
- data/lib/redis/errors.rb +20 -50
- data/lib/redis/hash_ring.rb +26 -26
- data/lib/redis/lib_identity.rb +105 -0
- data/lib/redis/pipeline.rb +47 -222
- data/lib/redis/subscribe.rb +51 -15
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +213 -188
- metadata +25 -59
- 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
|
@@ -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,37 @@ 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 [Integer] :limit maximum count of entries to be evicted, requires approximate trimming
|
|
48
|
+
# @option opts [Boolean] :nomkstream whether to add NOMKSTREAM, default is not to add
|
|
49
49
|
#
|
|
50
50
|
# @return [String] the entry id
|
|
51
|
-
def xadd(key, entry, approximate: nil, maxlen: nil, id: '*')
|
|
51
|
+
def xadd(key, entry, approximate: nil, maxlen: nil, minid: nil, limit: nil, nomkstream: nil, id: '*')
|
|
52
52
|
args = [:xadd, key]
|
|
53
|
+
args << 'NOMKSTREAM' if nomkstream
|
|
53
54
|
if maxlen
|
|
55
|
+
raise ArgumentError, "can't supply both maxlen and minid" if minid
|
|
56
|
+
|
|
54
57
|
args << "MAXLEN"
|
|
55
58
|
args << "~" if approximate
|
|
56
59
|
args << maxlen
|
|
60
|
+
elsif minid
|
|
61
|
+
args << "MINID"
|
|
62
|
+
args << "~" if approximate
|
|
63
|
+
args << minid
|
|
57
64
|
end
|
|
65
|
+
args.concat(['LIMIT', limit]) if limit
|
|
58
66
|
args << id
|
|
59
|
-
args.concat(entry.
|
|
67
|
+
args.concat(entry.flatten)
|
|
60
68
|
send_command(args)
|
|
61
69
|
end
|
|
62
70
|
|
|
@@ -66,14 +74,30 @@ class Redis
|
|
|
66
74
|
# redis.xtrim('mystream', 1000)
|
|
67
75
|
# @example With options
|
|
68
76
|
# redis.xtrim('mystream', 1000, approximate: true)
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
# @
|
|
77
|
+
# @example With strategy
|
|
78
|
+
# redis.xtrim('mystream', '1-0', strategy: 'MINID')
|
|
79
|
+
#
|
|
80
|
+
# @overload xtrim(key, maxlen, strategy: 'MAXLEN', approximate: true)
|
|
81
|
+
# @param key [String] the stream key
|
|
82
|
+
# @param maxlen [Integer] max length of entries
|
|
83
|
+
# @param strategy [String] the limit strategy, must be MAXLEN
|
|
84
|
+
# @param approximate [Boolean] whether to add `~` modifier of maxlen or not
|
|
85
|
+
# @param limit [Integer] maximum count of entries to be evicted
|
|
86
|
+
# @overload xtrim(key, minid, strategy: 'MINID', approximate: true)
|
|
87
|
+
# @param key [String] the stream key
|
|
88
|
+
# @param minid [String] minimum id of entries
|
|
89
|
+
# @param strategy [String] the limit strategy, must be MINID
|
|
90
|
+
# @param approximate [Boolean] whether to add `~` modifier of minid or not
|
|
91
|
+
# @param limit [Integer] maximum count of entries to be evicted
|
|
73
92
|
#
|
|
74
93
|
# @return [Integer] the number of entries actually deleted
|
|
75
|
-
def xtrim(key,
|
|
76
|
-
|
|
94
|
+
def xtrim(key, len_or_id, strategy: 'MAXLEN', approximate: false, limit: nil)
|
|
95
|
+
strategy = strategy.to_s.upcase
|
|
96
|
+
|
|
97
|
+
args = [:xtrim, key, strategy]
|
|
98
|
+
args << '~' if approximate
|
|
99
|
+
args << len_or_id
|
|
100
|
+
args.concat(['LIMIT', limit]) if limit
|
|
77
101
|
send_command(args)
|
|
78
102
|
end
|
|
79
103
|
|
|
@@ -113,7 +137,7 @@ class Redis
|
|
|
113
137
|
def xrange(key, start = '-', range_end = '+', count: nil)
|
|
114
138
|
args = [:xrange, key, start, range_end]
|
|
115
139
|
args.concat(['COUNT', count]) if count
|
|
116
|
-
|
|
140
|
+
send_command(args, &HashifyStreamEntries)
|
|
117
141
|
end
|
|
118
142
|
|
|
119
143
|
# Fetches entries of the stream in descending order.
|
|
@@ -159,18 +183,28 @@ class Redis
|
|
|
159
183
|
# redis.xread(%w[mystream1 mystream2], %w[0-0 0-0])
|
|
160
184
|
# @example With count option
|
|
161
185
|
# redis.xread('mystream', '0-0', count: 2)
|
|
186
|
+
# @example With max_count option
|
|
187
|
+
# redis.xread(%w[mystream1 mystream2], %w[0-0 0-0], max_count: 10)
|
|
162
188
|
# @example With block option
|
|
163
189
|
# redis.xread('mystream', '$', block: 1000)
|
|
164
190
|
#
|
|
165
|
-
# @param keys
|
|
166
|
-
# @param ids
|
|
167
|
-
# @param count
|
|
168
|
-
# @param
|
|
191
|
+
# @param keys [Array<String>] one or multiple stream keys
|
|
192
|
+
# @param ids [Array<String>] one or multiple entry ids
|
|
193
|
+
# @param count [Integer] the number of entries as limit per stream
|
|
194
|
+
# @param max_count [Integer] the total number of entries as limit across all streams
|
|
195
|
+
# combined, must be greater than or equal to `count` when both are given (Redis 8.10+).
|
|
196
|
+
# Defaults to unlimited.
|
|
197
|
+
# @param max_size [Integer] soft cap on the total reply size in bytes across all
|
|
198
|
+
# streams combined, measured on the serialized server reply including protocol overhead;
|
|
199
|
+
# a single oversized first entry can still be returned (Redis 8.10+). Defaults to unlimited.
|
|
200
|
+
# @param block [Integer] the number of milliseconds as blocking timeout
|
|
169
201
|
#
|
|
170
202
|
# @return [Hash{String => Hash{String => Hash}}] the entries
|
|
171
|
-
def xread(keys, ids, count: nil, block: nil)
|
|
203
|
+
def xread(keys, ids, count: nil, max_count: nil, max_size: nil, block: nil)
|
|
172
204
|
args = [:xread]
|
|
173
205
|
args << 'COUNT' << count if count
|
|
206
|
+
args << 'MAXCOUNT' << Integer(max_count) if max_count
|
|
207
|
+
args << 'MAXSIZE' << Integer(max_size) if max_size
|
|
174
208
|
args << 'BLOCK' << block.to_i if block
|
|
175
209
|
_xread(args, keys, ids, block)
|
|
176
210
|
end
|
|
@@ -221,14 +255,22 @@ class Redis
|
|
|
221
255
|
# @param ids [Array<String>] one or multiple entry ids
|
|
222
256
|
# @param opts [Hash] several options for `XREADGROUP` command
|
|
223
257
|
#
|
|
224
|
-
# @option opts [Integer] :count the number of entries as limit
|
|
258
|
+
# @option opts [Integer] :count the number of entries as limit per stream
|
|
259
|
+
# @option opts [Integer] :max_count the total number of entries as limit across all streams
|
|
260
|
+
# combined, must be greater than or equal to `count` when both are given (Redis 8.10+).
|
|
261
|
+
# Defaults to unlimited.
|
|
262
|
+
# @option opts [Integer] :max_size soft cap on the total reply size in bytes across all
|
|
263
|
+
# streams combined, measured on the serialized server reply including protocol overhead;
|
|
264
|
+
# a single oversized first entry can still be returned (Redis 8.10+). Defaults to unlimited.
|
|
225
265
|
# @option opts [Integer] :block the number of milliseconds as blocking timeout
|
|
226
266
|
# @option opts [Boolean] :noack whether message loss is acceptable or not
|
|
227
267
|
#
|
|
228
268
|
# @return [Hash{String => Hash{String => Hash}}] the entries
|
|
229
|
-
def xreadgroup(group, consumer, keys, ids, count: nil, block: nil, noack: nil)
|
|
269
|
+
def xreadgroup(group, consumer, keys, ids, count: nil, max_count: nil, max_size: nil, block: nil, noack: nil)
|
|
230
270
|
args = [:xreadgroup, 'GROUP', group, consumer]
|
|
231
271
|
args << 'COUNT' << count if count
|
|
272
|
+
args << 'MAXCOUNT' << Integer(max_count) if max_count
|
|
273
|
+
args << 'MAXSIZE' << Integer(max_size) if max_size
|
|
232
274
|
args << 'BLOCK' << block.to_i if block
|
|
233
275
|
args << 'NOACK' if noack
|
|
234
276
|
_xread(args, keys, ids, block)
|
|
@@ -334,6 +376,8 @@ class Redis
|
|
|
334
376
|
# redis.xpending('mystream', 'mygroup')
|
|
335
377
|
# @example With range options
|
|
336
378
|
# redis.xpending('mystream', 'mygroup', '-', '+', 10)
|
|
379
|
+
# @example With range and idle time options
|
|
380
|
+
# redis.xpending('mystream', 'mygroup', '-', '+', 10, idle: 9000)
|
|
337
381
|
# @example With range and consumer options
|
|
338
382
|
# redis.xpending('mystream', 'mygroup', '-', '+', 10, 'consumer1')
|
|
339
383
|
#
|
|
@@ -344,10 +388,13 @@ class Redis
|
|
|
344
388
|
# @param count [Integer] count the number of entries as limit
|
|
345
389
|
# @param consumer [String] the consumer name
|
|
346
390
|
#
|
|
391
|
+
# @option opts [Integer] :idle pending message minimum idle time in milliseconds
|
|
392
|
+
#
|
|
347
393
|
# @return [Hash] the summary of pending entries
|
|
348
394
|
# @return [Array<Hash>] the pending entries details if options were specified
|
|
349
|
-
def xpending(key, group, *args)
|
|
395
|
+
def xpending(key, group, *args, idle: nil)
|
|
350
396
|
command_args = [:xpending, key, group]
|
|
397
|
+
command_args << 'IDLE' << Integer(idle) if idle
|
|
351
398
|
case args.size
|
|
352
399
|
when 0, 3, 4
|
|
353
400
|
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
|
data/lib/redis/commands.rb
CHANGED
|
@@ -8,8 +8,10 @@ require "redis/commands/hashes"
|
|
|
8
8
|
require "redis/commands/hyper_log_log"
|
|
9
9
|
require "redis/commands/keys"
|
|
10
10
|
require "redis/commands/lists"
|
|
11
|
+
require "redis/commands/modules/json"
|
|
11
12
|
require "redis/commands/pubsub"
|
|
12
13
|
require "redis/commands/scripting"
|
|
14
|
+
require "redis/commands/modules/search"
|
|
13
15
|
require "redis/commands/server"
|
|
14
16
|
require "redis/commands/sets"
|
|
15
17
|
require "redis/commands/sorted_sets"
|
|
@@ -27,8 +29,10 @@ class Redis
|
|
|
27
29
|
include HyperLogLog
|
|
28
30
|
include Keys
|
|
29
31
|
include Lists
|
|
32
|
+
include Json
|
|
30
33
|
include Pubsub
|
|
31
34
|
include Scripting
|
|
35
|
+
include Search
|
|
32
36
|
include Server
|
|
33
37
|
include Sets
|
|
34
38
|
include SortedSets
|
|
@@ -40,12 +44,7 @@ class Redis
|
|
|
40
44
|
# where the method call will return nil. Propagate the nil instead of falsely
|
|
41
45
|
# returning false.
|
|
42
46
|
Boolify = lambda { |value|
|
|
43
|
-
|
|
44
|
-
when Integer
|
|
45
|
-
value > 0
|
|
46
|
-
else
|
|
47
|
-
value
|
|
48
|
-
end
|
|
47
|
+
value != 0 unless value.nil?
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
BoolifySet = lambda { |value|
|
|
@@ -60,7 +59,9 @@ class Redis
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
Hashify = lambda { |value|
|
|
63
|
-
if value.
|
|
62
|
+
if value.is_a?(Hash) # RESP3 already returns a map
|
|
63
|
+
value
|
|
64
|
+
elsif value.respond_to?(:each_slice) # RESP2 flat [k, v, k, v, ...]
|
|
64
65
|
value.each_slice(2).to_h
|
|
65
66
|
else
|
|
66
67
|
value
|
|
@@ -68,10 +69,12 @@ class Redis
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
Pairify = lambda { |value|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
return value unless value.respond_to?(:each_slice)
|
|
73
|
+
|
|
74
|
+
if value.first.is_a?(Array) # RESP3 already returns [[k, v], ...]
|
|
74
75
|
value
|
|
76
|
+
else # RESP2 flat [k, v, k, v, ...]
|
|
77
|
+
value.each_slice(2).to_a
|
|
75
78
|
end
|
|
76
79
|
}
|
|
77
80
|
|
|
@@ -88,11 +91,20 @@ class Redis
|
|
|
88
91
|
end
|
|
89
92
|
}
|
|
90
93
|
|
|
94
|
+
FloatifyPair = lambda { |(first, score)|
|
|
95
|
+
[first, Floatify.call(score)]
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
FloatifyPairs = lambda { |value|
|
|
92
99
|
return value unless value.respond_to?(:each_slice)
|
|
93
100
|
|
|
94
|
-
value.
|
|
95
|
-
|
|
101
|
+
if value.first.is_a?(Array) # RESP3 already returns [[member, score], ...]
|
|
102
|
+
# Scores arrive as native doubles, so the pairs are already in the final shape and
|
|
103
|
+
# re-mapping would only re-allocate identical arrays. Floatify only transforms Strings, so
|
|
104
|
+
# unless a score came back as one (it shouldn't under RESP3) return the parser's array as-is.
|
|
105
|
+
value.first.last.is_a?(String) ? value.map(&FloatifyPair) : value
|
|
106
|
+
else # RESP2 flat [member, score, member, score, ...]
|
|
107
|
+
value.each_slice(2).map(&FloatifyPair)
|
|
96
108
|
end
|
|
97
109
|
}
|
|
98
110
|
|
|
@@ -124,7 +136,9 @@ class Redis
|
|
|
124
136
|
HashifyStreamAutoclaim = lambda { |reply|
|
|
125
137
|
{
|
|
126
138
|
'next' => reply[0],
|
|
127
|
-
'entries' => reply[1].map
|
|
139
|
+
'entries' => reply[1].compact.map do |entry, values|
|
|
140
|
+
[entry, values.each_slice(2)&.to_h]
|
|
141
|
+
end
|
|
128
142
|
}
|
|
129
143
|
}
|
|
130
144
|
|
|
@@ -202,8 +216,8 @@ class Redis
|
|
|
202
216
|
# hash, are up to consumers.
|
|
203
217
|
#
|
|
204
218
|
# Redis error replies are raised as Ruby exceptions.
|
|
205
|
-
def call(*command)
|
|
206
|
-
send_command(command)
|
|
219
|
+
def call(*command, &block)
|
|
220
|
+
send_command(command, &block)
|
|
207
221
|
end
|
|
208
222
|
|
|
209
223
|
# Interact with the sentinel command (masters, master, slaves, failover)
|
|
@@ -218,14 +232,19 @@ class Redis
|
|
|
218
232
|
when "get-master-addr-by-name"
|
|
219
233
|
reply
|
|
220
234
|
else
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
235
|
+
case reply
|
|
236
|
+
when Array
|
|
237
|
+
if reply.empty?
|
|
238
|
+
reply # empty list (e.g. sentinels/slaves with no entries) stays []; don't Hashify to {}
|
|
224
239
|
else
|
|
225
|
-
|
|
240
|
+
case reply[0]
|
|
241
|
+
when Array then reply.map(&Hashify) # RESP2: list of flat [k, v, ...] arrays
|
|
242
|
+
when Hash then reply # RESP3: list of maps (already hashes)
|
|
243
|
+
else Hashify.call(reply) # RESP2: a single flat [k, v, ...] array
|
|
244
|
+
end
|
|
226
245
|
end
|
|
227
246
|
else
|
|
228
|
-
reply
|
|
247
|
+
reply # RESP3 single map, or a scalar reply
|
|
229
248
|
end
|
|
230
249
|
end
|
|
231
250
|
end
|