redis-clustering 5.0.0 → 5.2.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/README.md +8 -2
- data/lib/redis/cluster/client.rb +34 -18
- data/lib/redis/cluster.rb +11 -0
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0390ca44d9f71661f4cfb1a7f8d1a396a84e204e992cf8a5d0755af4232cb7ac'
|
4
|
+
data.tar.gz: 923cffa3fc0a5a2aaecb4d669ea685e25047c7dc70f932f3e807e6e381fc3ecb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4c5f9903044360cd0317a2ad75d0c41cbd8627c34da86c9cca3471ef78e0256778c15f997f0073386b8dbfa38ca906ab03b31efb3b7c190b7412a0d6bdd1987
|
7
|
+
data.tar.gz: 4e331655c8142429b1fbee72eec3c1fd26b42f5fa4e33156a0f3415151bd7bc3b9da85e604d464b4db33c2425d6a2b910718a6b6108ede5e7bc30635371ea33f
|
data/README.md
CHANGED
@@ -39,6 +39,12 @@ If you want [the connection to be able to read from any replica](https://redis.i
|
|
39
39
|
Redis::Cluster.new(nodes: nodes, replica: true)
|
40
40
|
```
|
41
41
|
|
42
|
+
Also, you can specify the `:replica_affinity` option if you want to prevent accessing cross availability zones.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
Redis::Cluster.new(nodes: nodes, replica: true, replica_affinity: :latency)
|
46
|
+
```
|
47
|
+
|
42
48
|
The calling code is responsible for [avoiding cross slot commands](https://redis.io/topics/cluster-spec#keys-distribution-model).
|
43
49
|
|
44
50
|
```ruby
|
@@ -59,13 +65,13 @@ redis.mget('{key}1', '{key}2')
|
|
59
65
|
Since Redis can return FQDN of nodes in reply to client since `7.*` with CLUSTER commands, we can use cluster feature with SSL/TLS connection like this:
|
60
66
|
|
61
67
|
```ruby
|
62
|
-
Redis.new(
|
68
|
+
Redis::Cluster.new(nodes: %w[rediss://foo.example.com:6379])
|
63
69
|
```
|
64
70
|
|
65
71
|
On the other hand, in Redis versions prior to `6.*`, you can specify options like the following if cluster mode is enabled and client has to connect to nodes via single endpoint with SSL/TLS.
|
66
72
|
|
67
73
|
```ruby
|
68
|
-
Redis.new(
|
74
|
+
Redis::Cluster.new(nodes: %w[rediss://foo-endpoint.example.com:6379], fixed_hostname: 'foo-endpoint.example.com')
|
69
75
|
```
|
70
76
|
|
71
77
|
In case of the above architecture, if you don't pass the `fixed_hostname` option to the client and servers return IP addresses of nodes, the client may fail to verify certificates.
|
data/lib/redis/cluster/client.rb
CHANGED
@@ -9,8 +9,10 @@ class Redis
|
|
9
9
|
RedisClient::Cluster::InitialSetupError => Redis::Cluster::InitialSetupError,
|
10
10
|
RedisClient::Cluster::OrchestrationCommandNotSupported => Redis::Cluster::OrchestrationCommandNotSupported,
|
11
11
|
RedisClient::Cluster::AmbiguousNodeError => Redis::Cluster::AmbiguousNodeError,
|
12
|
-
RedisClient::Cluster::ErrorCollection => Redis::Cluster::CommandErrorCollection
|
13
|
-
|
12
|
+
RedisClient::Cluster::ErrorCollection => Redis::Cluster::CommandErrorCollection,
|
13
|
+
RedisClient::Cluster::Transaction::ConsistencyError => Redis::Cluster::TransactionConsistencyError,
|
14
|
+
RedisClient::Cluster::NodeMightBeDown => Redis::Cluster::NodeMightBeDown,
|
15
|
+
)
|
14
16
|
|
15
17
|
class << self
|
16
18
|
def config(**kwargs)
|
@@ -20,21 +22,42 @@ class Redis
|
|
20
22
|
def sentinel(**kwargs)
|
21
23
|
super(protocol: 2, **kwargs)
|
22
24
|
end
|
25
|
+
|
26
|
+
def translate_error!(error, mapping: ERROR_MAPPING)
|
27
|
+
case error
|
28
|
+
when RedisClient::Cluster::ErrorCollection
|
29
|
+
error.errors.each do |_node, node_error|
|
30
|
+
if node_error.is_a?(RedisClient::AuthenticationError)
|
31
|
+
raise mapping.fetch(node_error.class), node_error.message, node_error.backtrace
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
remapped_node_errors = error.errors.map do |node_key, node_error|
|
36
|
+
remapped = mapping.fetch(node_error.class, node_error.class).new(node_error.message)
|
37
|
+
remapped.set_backtrace node_error.backtrace
|
38
|
+
[node_key, remapped]
|
39
|
+
end.to_h
|
40
|
+
|
41
|
+
raise(Redis::Cluster::CommandErrorCollection.new(remapped_node_errors, error.message).tap do |remapped|
|
42
|
+
remapped.set_backtrace error.backtrace
|
43
|
+
end)
|
44
|
+
else
|
45
|
+
Redis::Client.translate_error!(error, mapping: mapping)
|
46
|
+
end
|
47
|
+
end
|
23
48
|
end
|
24
49
|
|
25
50
|
def initialize(*)
|
26
51
|
handle_errors { super }
|
27
|
-
@inherit_socket = false
|
28
|
-
@pid = Process.pid
|
29
52
|
end
|
30
53
|
ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
|
31
54
|
|
32
55
|
def id
|
33
|
-
@router.
|
56
|
+
@router.node_keys.join(' ')
|
34
57
|
end
|
35
58
|
|
36
59
|
def server_url
|
37
|
-
@router.
|
60
|
+
@router.node_keys
|
38
61
|
end
|
39
62
|
|
40
63
|
def connected?
|
@@ -67,27 +90,20 @@ class Redis
|
|
67
90
|
handle_errors { super(timeout, command, &block) }
|
68
91
|
end
|
69
92
|
|
70
|
-
def pipelined(&block)
|
71
|
-
handle_errors { super(&block) }
|
93
|
+
def pipelined(exception: true, &block)
|
94
|
+
handle_errors { super(exception: exception, &block) }
|
72
95
|
end
|
73
96
|
|
74
|
-
def multi(&block)
|
75
|
-
handle_errors { super(&block) }
|
97
|
+
def multi(watch: nil, &block)
|
98
|
+
handle_errors { super(watch: watch, &block) }
|
76
99
|
end
|
77
100
|
|
78
101
|
private
|
79
102
|
|
80
103
|
def handle_errors
|
81
104
|
yield
|
82
|
-
rescue RedisClient::Cluster::ErrorCollection => error
|
83
|
-
error.errors.each do |_node, node_error|
|
84
|
-
if node_error.is_a?(RedisClient::AuthenticationError)
|
85
|
-
raise ERROR_MAPPING.fetch(node_error.class), node_error.message, node_error.backtrace
|
86
|
-
end
|
87
|
-
end
|
88
|
-
raise ERROR_MAPPING.fetch(error.class), error.message, error.backtrace
|
89
105
|
rescue ::RedisClient::Error => error
|
90
|
-
|
106
|
+
Redis::Cluster::Client.translate_error!(error)
|
91
107
|
end
|
92
108
|
end
|
93
109
|
end
|
data/lib/redis/cluster.rb
CHANGED
@@ -38,6 +38,12 @@ class Redis
|
|
38
38
|
class AmbiguousNodeError < BaseError
|
39
39
|
end
|
40
40
|
|
41
|
+
class TransactionConsistencyError < BaseError
|
42
|
+
end
|
43
|
+
|
44
|
+
class NodeMightBeDown < BaseError
|
45
|
+
end
|
46
|
+
|
41
47
|
def connection
|
42
48
|
raise NotImplementedError, "Redis::Cluster doesn't implement #connection"
|
43
49
|
end
|
@@ -53,6 +59,7 @@ class Redis
|
|
53
59
|
# @option options [Boolean] :inherit_socket (false) Whether to use socket in forked process or not
|
54
60
|
# @option options [Array<String, Hash{Symbol => String, Integer}>] :nodes List of cluster nodes to contact
|
55
61
|
# @option options [Boolean] :replica Whether to use readonly replica nodes in Redis Cluster or not
|
62
|
+
# @option options [Symbol] :replica_affinity scale reading strategy, currently supported: `:random`, `:latency`
|
56
63
|
# @option options [String] :fixed_hostname Specify a FQDN if cluster mode enabled and
|
57
64
|
# client has to connect nodes via single endpoint with SSL/TLS
|
58
65
|
# @option options [Class] :connector Class of custom connector
|
@@ -89,6 +96,10 @@ class Redis
|
|
89
96
|
send_command([:cluster, subcommand] + args, &block)
|
90
97
|
end
|
91
98
|
|
99
|
+
def watch(*keys, &block)
|
100
|
+
synchronize { |c| c.call_v([:watch] + keys, &block) }
|
101
|
+
end
|
102
|
+
|
92
103
|
private
|
93
104
|
|
94
105
|
def initialize_client(options)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-clustering
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.2.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:
|
19
|
+
date: 2024-04-15 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: redis
|
@@ -24,28 +24,28 @@ dependencies:
|
|
24
24
|
requirements:
|
25
25
|
- - '='
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 5.
|
27
|
+
version: 5.2.0
|
28
28
|
type: :runtime
|
29
29
|
prerelease: false
|
30
30
|
version_requirements: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - '='
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 5.
|
34
|
+
version: 5.2.0
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: redis-cluster-client
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: 0.7.11
|
42
42
|
type: :runtime
|
43
43
|
prerelease: false
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 0.7.11
|
49
49
|
description: |2
|
50
50
|
A Ruby client that tries to match Redis' Cluster API one-to-one, while still
|
51
51
|
providing an idiomatic interface.
|
@@ -68,9 +68,9 @@ licenses:
|
|
68
68
|
metadata:
|
69
69
|
bug_tracker_uri: https://github.com/redis/redis-rb/issues
|
70
70
|
changelog_uri: https://github.com/redis/redis-rb/blob/master/cluster/CHANGELOG.md
|
71
|
-
documentation_uri: https://www.rubydoc.info/gems/redis/5.
|
71
|
+
documentation_uri: https://www.rubydoc.info/gems/redis/5.2.0
|
72
72
|
homepage_uri: https://github.com/redis/redis-rb/blob/master/cluster
|
73
|
-
source_code_uri: https://github.com/redis/redis-rb/tree/v5.
|
73
|
+
source_code_uri: https://github.com/redis/redis-rb/tree/v5.2.0/cluster
|
74
74
|
post_install_message:
|
75
75
|
rdoc_options: []
|
76
76
|
require_paths:
|
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: '0'
|
88
88
|
requirements: []
|
89
|
-
rubygems_version: 3.
|
89
|
+
rubygems_version: 3.5.3
|
90
90
|
signing_key:
|
91
91
|
specification_version: 4
|
92
92
|
summary: A Ruby client library for Redis Cluster
|