redis-cluster-client 0.7.8 → 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41d87ce45a108ff8ec7d3c17805276d5ba7df11d577de3f7d6b1176bdd297ed0
4
- data.tar.gz: 7118539907bb755225ba908cf160ad8af73aeb5204820682ca3fc3a67813f3cb
3
+ metadata.gz: 5aa02a0e3934e8246e948260f2a4457b324de2377e7ec2e00fe9bf03a52f5ee4
4
+ data.tar.gz: 9f97a22af58eb64c64a6b73a79c2947bad06318e17bca235a5aa59fae35aad1d
5
5
  SHA512:
6
- metadata.gz: 96e3c0f9c2860002642e079b756065e32f04891cd793dce9efcb74bb87a13683b14fee13c039693d99599549fee7ace68d54561b8c730d5e9eb7bb937a82c57d
7
- data.tar.gz: 2e512b774b5778e3f7a2a3557bb45d97971d209c787494a19d81e0d8146f5d51bbef7940f37fa38f7587e1037185e23fa27ca8d48a46225ced6640be8425198e
6
+ metadata.gz: 2e8fcf1be08ba5c2582ad112455b02815410a81834b55bfc0035e0971556ff7b443e60a48a4cc2f5c94fdd81d09a5d03d3c261b4e0afb13ac9f38da5d4f0ab64
7
+ data.tar.gz: 77f17d9e003384f34e5719f0e84f70c8a04f7de196974fc5af830e4825827b01d7df94b4eb887d4a1a4a77f43caa989cfdcbb1e874d807503bf9ef254ea95a0d
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'redis_client'
4
- require 'redis_client/cluster/key_slot_converter'
5
4
  require 'redis_client/cluster/transaction'
6
5
 
7
6
  class RedisClient
@@ -12,15 +11,14 @@ class RedisClient
12
11
  end
13
12
 
14
13
  def watch(keys)
15
- ensure_safe_keys(keys)
16
- node = find_node(keys)
17
- cnt = 0 # We assume redirects occurred when incrementing it.
14
+ slot = find_slot(keys)
15
+ raise ::RedisClient::Cluster::Transaction::ConsistencyError, "unsafe watch: #{keys.join(' ')}" if slot.nil?
18
16
 
17
+ node = @router.find_primary_node_by_slot(slot)
19
18
  @router.handle_redirection(node, retry_count: 1) do |nd|
20
- cnt += 1
21
19
  nd.with do |c|
22
20
  c.call('WATCH', *keys)
23
- reply = yield(c, cnt > 1)
21
+ reply = yield(c, slot)
24
22
  c.call('UNWATCH')
25
23
  reply
26
24
  end
@@ -29,29 +27,14 @@ class RedisClient
29
27
 
30
28
  private
31
29
 
32
- def ensure_safe_keys(keys)
33
- return if safe?(keys)
30
+ def find_slot(keys)
31
+ return if keys.empty?
32
+ return if keys.any? { |k| k.nil? || k.empty? }
34
33
 
35
- raise ::RedisClient::Cluster::Transaction::ConsistencyError, "unsafe watch: #{keys.join(' ')}"
36
- end
37
-
38
- def safe?(keys)
39
- return false if keys.empty?
40
-
41
- slots = keys.map do |k|
42
- return false if k.nil? || k.empty?
43
-
44
- ::RedisClient::Cluster::KeySlotConverter.convert(k)
45
- end
46
-
47
- slots.uniq.size == 1
48
- end
49
-
50
- def find_node(keys)
51
- node_key = @router.find_primary_node_key(['WATCH', *keys])
52
- return @router.find_node(node_key) unless node_key.nil?
34
+ slots = keys.map { |k| @router.find_slot_by_key(k) }
35
+ return if slots.uniq.size != 1
53
36
 
54
- raise ::RedisClient::Cluster::Transaction::ConsistencyError, "couldn't determine the node"
37
+ slots.first
55
38
  end
56
39
  end
57
40
  end
@@ -179,6 +179,16 @@ class RedisClient
179
179
  find_node_key_by_key(key, primary: true)
180
180
  end
181
181
 
182
+ def find_slot(command)
183
+ find_slot_by_key(@command.extract_first_key(command))
184
+ end
185
+
186
+ def find_slot_by_key(key)
187
+ return if key.empty?
188
+
189
+ ::RedisClient::Cluster::KeySlotConverter.convert(key)
190
+ end
191
+
182
192
  def find_node(node_key, retry_count: 3)
183
193
  @node.find_by(node_key)
184
194
  rescue ::RedisClient::Cluster::Node::ReloadNeeded
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'redis_client'
4
4
  require 'redis_client/cluster/pipeline'
5
- require 'redis_client/cluster/node_key'
6
5
 
7
6
  class RedisClient
8
7
  class Cluster
@@ -10,7 +9,7 @@ class RedisClient
10
9
  ConsistencyError = Class.new(::RedisClient::Error)
11
10
  MAX_REDIRECTION = 2
12
11
 
13
- def initialize(router, command_builder, node: nil, resharding: false)
12
+ def initialize(router, command_builder, node: nil, slot: nil)
14
13
  @router = router
15
14
  @command_builder = command_builder
16
15
  @retryable = true
@@ -18,7 +17,7 @@ class RedisClient
18
17
  @pending_commands = []
19
18
  @node = node
20
19
  prepare_tx unless @node.nil?
21
- @resharding_state = resharding
20
+ @watching_slot = slot
22
21
  end
23
22
 
24
23
  def call(*command, **kwargs, &block)
@@ -111,7 +110,7 @@ class RedisClient
111
110
  client.middlewares.call_pipelined(commands, client.config) do
112
111
  connection.call_pipelined(commands, nil)
113
112
  rescue ::RedisClient::CommandError => e
114
- return handle_command_error!(client, commands, e, redirect: redirect) unless redirect.zero?
113
+ return handle_command_error!(commands, e, redirect: redirect) unless redirect.zero?
115
114
 
116
115
  raise
117
116
  end
@@ -140,15 +139,15 @@ class RedisClient
140
139
  results
141
140
  end
142
141
 
143
- def handle_command_error!(client, commands, err, redirect:) # rubocop:disable Metrics/AbcSize
142
+ def handle_command_error!(commands, err, redirect:) # rubocop:disable Metrics/AbcSize
144
143
  if err.message.start_with?('CROSSSLOT')
145
144
  raise ConsistencyError, "#{err.message}: #{err.command}"
146
145
  elsif err.message.start_with?('MOVED')
147
- ensure_the_same_node!(client, commands)
146
+ ensure_the_same_slot!(commands)
148
147
  node = @router.assign_redirection_node(err.message)
149
148
  send_transaction(node, redirect: redirect - 1)
150
149
  elsif err.message.start_with?('ASK')
151
- ensure_the_same_node!(client, commands)
150
+ ensure_the_same_slot!(commands)
152
151
  node = @router.assign_asking_node(err.message)
153
152
  try_asking(node) ? send_transaction(node, redirect: redirect - 1) : err
154
153
  else
@@ -156,12 +155,10 @@ class RedisClient
156
155
  end
157
156
  end
158
157
 
159
- def ensure_the_same_node!(client, commands)
160
- node_keys = commands.map { |command| @router.find_primary_node_key(command) }.compact.uniq
161
- expected_node_key = ::RedisClient::Cluster::NodeKey.build_from_client(client)
162
-
163
- return if !@resharding_state && node_keys.size == 1 && node_keys.first == expected_node_key
164
- return if @resharding_state && node_keys.size == 1
158
+ def ensure_the_same_slot!(commands)
159
+ slots = commands.map { |command| @router.find_slot(command) }.compact.uniq
160
+ return if slots.size == 1 && @watching_slot.nil?
161
+ return if slots.size == 1 && @watching_slot == slots.first
165
162
 
166
163
  raise(ConsistencyError, "the transaction should be executed to a slot in a node: #{commands}")
167
164
  end
@@ -98,9 +98,9 @@ class RedisClient
98
98
  return transaction.execute
99
99
  end
100
100
 
101
- ::RedisClient::Cluster::OptimisticLocking.new(@router).watch(watch) do |c, resharding|
101
+ ::RedisClient::Cluster::OptimisticLocking.new(@router).watch(watch) do |c, slot|
102
102
  transaction = ::RedisClient::Cluster::Transaction.new(
103
- @router, @command_builder, node: c, resharding: resharding
103
+ @router, @command_builder, node: c, slot: slot
104
104
  )
105
105
  yield transaction
106
106
  transaction.execute
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-cluster-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.8
4
+ version: 0.7.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taishi Kasuga