redis 4.3.1 → 4.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 +8 -0
- data/lib/redis.rb +88 -0
- data/lib/redis/client.rb +2 -0
- data/lib/redis/cluster.rb +8 -12
- data/lib/redis/cluster/node.rb +2 -1
- data/lib/redis/distributed.rb +7 -0
- data/lib/redis/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5ff2ee4b6a6f2b087ac26bf96a3c1769cf42f70ea90008361157f7ef04cdb14
|
4
|
+
data.tar.gz: f2c24654294c4fa81a5cff4ddb545bc59e6f85b64ee61273278cb1e286a4edb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d88c6621659a178dca04d3ca62f25520f5f1a846b6300f93fb008966551fb4795a3e6c37810f99ea18f77a6292b955fa180ae3e06f8c90df7e6a3ca27087ae1
|
7
|
+
data.tar.gz: 1427cc268e867872388f214184d23a5c6062104fcb9d1e50d6026dd9daf6e51b9833866fee9fcf80c7a64e4de705295de8399d8e8ac22fa890bf358bd63ff707
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 4.4.0
|
4
|
+
|
5
|
+
* Redis cluster: fix cross-slot validation in pipelines. Fix ##1019.
|
6
|
+
* Add support for `XAUTOCLAIM`. See #1018.
|
7
|
+
* Properly issue `READONLY` when reconnecting to replicas. Fix #1017.
|
8
|
+
* Make `del` a noop if passed an empty list of keys. See #998.
|
9
|
+
* Add support for `ZINTER`. See #995.
|
10
|
+
|
3
11
|
# 4.3.1
|
4
12
|
|
5
13
|
* Fix password authentication against redis server 5 and older.
|
data/lib/redis.rb
CHANGED
@@ -555,6 +555,9 @@ class Redis
|
|
555
555
|
# @param [String, Array<String>] keys
|
556
556
|
# @return [Integer] number of keys that were deleted
|
557
557
|
def del(*keys)
|
558
|
+
keys.flatten!(1)
|
559
|
+
return 0 if keys.empty?
|
560
|
+
|
558
561
|
synchronize do |client|
|
559
562
|
client.call([:del] + keys)
|
560
563
|
end
|
@@ -2062,6 +2065,45 @@ class Redis
|
|
2062
2065
|
end
|
2063
2066
|
end
|
2064
2067
|
|
2068
|
+
# Return the intersection of multiple sorted sets
|
2069
|
+
#
|
2070
|
+
# @example Retrieve the intersection of `2*zsetA` and `1*zsetB`
|
2071
|
+
# redis.zinter("zsetA", "zsetB", :weights => [2.0, 1.0])
|
2072
|
+
# # => ["v1", "v2"]
|
2073
|
+
# @example Retrieve the intersection of `2*zsetA` and `1*zsetB`, and their scores
|
2074
|
+
# redis.zinter("zsetA", "zsetB", :weights => [2.0, 1.0], :with_scores => true)
|
2075
|
+
# # => [["v1", 3.0], ["v2", 6.0]]
|
2076
|
+
#
|
2077
|
+
# @param [String, Array<String>] keys one or more keys to intersect
|
2078
|
+
# @param [Hash] options
|
2079
|
+
# - `:weights => [Float, Float, ...]`: weights to associate with source
|
2080
|
+
# sorted sets
|
2081
|
+
# - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
|
2082
|
+
# - `:with_scores => true`: include scores in output
|
2083
|
+
#
|
2084
|
+
# @return [Array<String>, Array<[String, Float]>]
|
2085
|
+
# - when `:with_scores` is not specified, an array of members
|
2086
|
+
# - when `:with_scores` is specified, an array with `[member, score]` pairs
|
2087
|
+
def zinter(*keys, weights: nil, aggregate: nil, with_scores: false)
|
2088
|
+
args = [:zinter, keys.size, *keys]
|
2089
|
+
|
2090
|
+
if weights
|
2091
|
+
args << "WEIGHTS"
|
2092
|
+
args.concat(weights)
|
2093
|
+
end
|
2094
|
+
|
2095
|
+
args << "AGGREGATE" << aggregate if aggregate
|
2096
|
+
|
2097
|
+
if with_scores
|
2098
|
+
args << "WITHSCORES"
|
2099
|
+
block = FloatifyPairs
|
2100
|
+
end
|
2101
|
+
|
2102
|
+
synchronize do |client|
|
2103
|
+
client.call(args, &block)
|
2104
|
+
end
|
2105
|
+
end
|
2106
|
+
|
2065
2107
|
# Intersect multiple sorted sets and store the resulting sorted set in a new
|
2066
2108
|
# key.
|
2067
2109
|
#
|
@@ -3238,6 +3280,38 @@ class Redis
|
|
3238
3280
|
synchronize { |client| client.call(args, &blk) }
|
3239
3281
|
end
|
3240
3282
|
|
3283
|
+
# Transfers ownership of pending stream entries that match the specified criteria.
|
3284
|
+
#
|
3285
|
+
# @example Claim next pending message stuck > 5 minutes and mark as retry
|
3286
|
+
# redis.xautoclaim('mystream', 'mygroup', 'consumer1', 3600000, '0-0')
|
3287
|
+
# @example Claim 50 next pending messages stuck > 5 minutes and mark as retry
|
3288
|
+
# redis.xclaim('mystream', 'mygroup', 'consumer1', 3600000, '0-0', count: 50)
|
3289
|
+
# @example Claim next pending message stuck > 5 minutes and don't mark as retry
|
3290
|
+
# redis.xclaim('mystream', 'mygroup', 'consumer1', 3600000, '0-0', justid: true)
|
3291
|
+
# @example Claim next pending message after this id stuck > 5 minutes and mark as retry
|
3292
|
+
# redis.xautoclaim('mystream', 'mygroup', 'consumer1', 3600000, '1641321233-0')
|
3293
|
+
#
|
3294
|
+
# @param key [String] the stream key
|
3295
|
+
# @param group [String] the consumer group name
|
3296
|
+
# @param consumer [String] the consumer name
|
3297
|
+
# @param min_idle_time [Integer] the number of milliseconds
|
3298
|
+
# @param start [String] entry id to start scanning from or 0-0 for everything
|
3299
|
+
# @param count [Integer] number of messages to claim (default 1)
|
3300
|
+
# @param justid [Boolean] whether to fetch just an array of entry ids or not.
|
3301
|
+
# Does not increment retry count when true
|
3302
|
+
#
|
3303
|
+
# @return [Hash{String => Hash}] the entries successfully claimed
|
3304
|
+
# @return [Array<String>] the entry ids successfully claimed if justid option is `true`
|
3305
|
+
def xautoclaim(key, group, consumer, min_idle_time, start, count: nil, justid: false)
|
3306
|
+
args = [:xautoclaim, key, group, consumer, min_idle_time, start]
|
3307
|
+
if count
|
3308
|
+
args << 'COUNT' << count.to_s
|
3309
|
+
end
|
3310
|
+
args << 'JUSTID' if justid
|
3311
|
+
blk = justid ? HashifyStreamAutoclaimJustId : HashifyStreamAutoclaim
|
3312
|
+
synchronize { |client| client.call(args, &blk) }
|
3313
|
+
end
|
3314
|
+
|
3241
3315
|
# Fetches not acknowledging pending entries
|
3242
3316
|
#
|
3243
3317
|
# @example With key and group
|
@@ -3448,6 +3522,20 @@ class Redis
|
|
3448
3522
|
end
|
3449
3523
|
}
|
3450
3524
|
|
3525
|
+
HashifyStreamAutoclaim = lambda { |reply|
|
3526
|
+
{
|
3527
|
+
'next' => reply[0],
|
3528
|
+
'entries' => reply[1].map { |entry| [entry[0], entry[1].each_slice(2).to_h] }
|
3529
|
+
}
|
3530
|
+
}
|
3531
|
+
|
3532
|
+
HashifyStreamAutoclaimJustId = lambda { |reply|
|
3533
|
+
{
|
3534
|
+
'next' => reply[0],
|
3535
|
+
'entries' => reply[1]
|
3536
|
+
}
|
3537
|
+
}
|
3538
|
+
|
3451
3539
|
HashifyStreamPendings = lambda { |reply|
|
3452
3540
|
{
|
3453
3541
|
'size' => reply[0],
|
data/lib/redis/client.rb
CHANGED
data/lib/redis/cluster.rb
CHANGED
@@ -78,11 +78,13 @@ class Redis
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def call_pipeline(pipeline)
|
81
|
-
node_keys
|
82
|
-
|
81
|
+
node_keys = pipeline.commands.map { |cmd| find_node_key(cmd, primary_only: true) }.compact.uniq
|
82
|
+
if node_keys.size > 1
|
83
|
+
raise(CrossSlotPipeliningError,
|
84
|
+
pipeline.commands.map { |cmd| @command.extract_first_key(cmd) }.reject(&:empty?).uniq)
|
85
|
+
end
|
83
86
|
|
84
|
-
|
85
|
-
try_send(node, :call_pipeline, pipeline)
|
87
|
+
try_send(find_node(node_keys.first), :call_pipeline, pipeline)
|
86
88
|
end
|
87
89
|
|
88
90
|
def call_with_timeout(command, timeout, &block)
|
@@ -253,14 +255,14 @@ class Redis
|
|
253
255
|
find_node(node_key)
|
254
256
|
end
|
255
257
|
|
256
|
-
def find_node_key(command)
|
258
|
+
def find_node_key(command, primary_only: false)
|
257
259
|
key = @command.extract_first_key(command)
|
258
260
|
return if key.empty?
|
259
261
|
|
260
262
|
slot = KeySlotConverter.convert(key)
|
261
263
|
return unless @slot.exists?(slot)
|
262
264
|
|
263
|
-
if @command.should_send_to_master?(command)
|
265
|
+
if @command.should_send_to_master?(command) || primary_only
|
264
266
|
@slot.find_node_key_of_master(slot)
|
265
267
|
else
|
266
268
|
@slot.find_node_key_of_slave(slot)
|
@@ -285,11 +287,5 @@ class Redis
|
|
285
287
|
@node.map(&:disconnect)
|
286
288
|
@node, @slot = fetch_cluster_info!(@option)
|
287
289
|
end
|
288
|
-
|
289
|
-
def extract_keys_in_pipeline(pipeline)
|
290
|
-
node_keys = pipeline.commands.map { |cmd| find_node_key(cmd) }.compact.uniq
|
291
|
-
command_keys = pipeline.commands.map { |cmd| @command.extract_first_key(cmd) }.reject(&:empty?)
|
292
|
-
[node_keys, command_keys]
|
293
|
-
end
|
294
290
|
end
|
295
291
|
end
|
data/lib/redis/cluster/node.rb
CHANGED
@@ -76,8 +76,9 @@ class Redis
|
|
76
76
|
clients = options.map do |node_key, option|
|
77
77
|
next if replica_disabled? && slave?(node_key)
|
78
78
|
|
79
|
+
option = option.merge(readonly: true) if slave?(node_key)
|
80
|
+
|
79
81
|
client = Client.new(option)
|
80
|
-
client.call(%i[readonly]) if slave?(node_key)
|
81
82
|
[node_key, client]
|
82
83
|
end
|
83
84
|
|
data/lib/redis/distributed.rb
CHANGED
@@ -674,6 +674,13 @@ class Redis
|
|
674
674
|
node_for(key).zcount(key, min, max)
|
675
675
|
end
|
676
676
|
|
677
|
+
# Get the intersection of multiple sorted sets
|
678
|
+
def zinter(*keys, **options)
|
679
|
+
ensure_same_node(:zinter, keys) do |node|
|
680
|
+
node.zinter(*keys, **options)
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
677
684
|
# Intersect multiple sorted sets and store the resulting sorted set in a new
|
678
685
|
# key.
|
679
686
|
def zinterstore(destination, keys, **options)
|
data/lib/redis/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Zygmuntowicz
|
@@ -16,7 +16,7 @@ authors:
|
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
|
-
date: 2021-
|
19
|
+
date: 2021-07-28 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: em-synchrony
|
@@ -102,9 +102,9 @@ licenses:
|
|
102
102
|
metadata:
|
103
103
|
bug_tracker_uri: https://github.com/redis/redis-rb/issues
|
104
104
|
changelog_uri: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md
|
105
|
-
documentation_uri: https://www.rubydoc.info/gems/redis/4.
|
105
|
+
documentation_uri: https://www.rubydoc.info/gems/redis/4.4.0
|
106
106
|
homepage_uri: https://github.com/redis/redis-rb
|
107
|
-
source_code_uri: https://github.com/redis/redis-rb/tree/v4.
|
107
|
+
source_code_uri: https://github.com/redis/redis-rb/tree/v4.4.0
|
108
108
|
post_install_message:
|
109
109
|
rdoc_options: []
|
110
110
|
require_paths:
|