redis-cluster-client 0.7.8 → 0.7.9

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 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