redis-cluster-client 0.3.4 → 0.3.5

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: 458c3d9cc4d1f6595510663cede0403953b2555ace0d3cae814663b23f69f1cb
4
- data.tar.gz: 01d2a34641e298ff7e99cc5f9edbad4ed152e5ca4f18e16181b9a4b84a2492c2
3
+ metadata.gz: a697c2bd33f615cb435ee48c11c301bba56cad4eac139f30db70a183d888d891
4
+ data.tar.gz: 52200e9400bd7bd7fde2019c52b6cf1e26c6c019cbf1ed12a25c2167cd7ac129
5
5
  SHA512:
6
- metadata.gz: 3680e6b8b1594001060eb2dea29eb60f0779bba6a43350246b1d5c7e47b1bb1e04a6e1188ac87c1228adac21e86347cb3820679d6c92b693d7f7fedabba88402
7
- data.tar.gz: 21927b8a14e9ad075e3808e736789c4339af907f5d99e16806273f1553c505e7fc86faabfa067b98f2a3dd7d45a41fb0f89e780e08825aa9df4317531871da5d
6
+ metadata.gz: 05dc86fd1aa3cbf3cd3f0fa43d9d1c8463fcbe9e0ce1bcfe094f6095fd92d878a4bb21e6d6fa62203e91f3dc642e5869552f0b83d579cfa158b791501e1cb600
7
+ data.tar.gz: 8f80c5072d4d1bdbeb3e2cb4c9f92493537a6d9002edd71426598844ba28a497171c055135bb19a1d89a325c194026195100f9a0aea89c0beac3d8e9424f7f58
@@ -40,12 +40,12 @@ class RedisClient
40
40
  private
41
41
 
42
42
  def measure_latencies(clients) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
43
- latencies = {}
44
-
43
+ latencies = nil
45
44
  clients.each_slice(::RedisClient::Cluster::Node::MAX_THREADS) do |chuncked_clients|
46
45
  threads = chuncked_clients.map do |k, v|
47
46
  Thread.new(k, v) do |node_key, client|
48
47
  Thread.pass
48
+ Thread.current.thread_variable_set(:node_key, node_key)
49
49
 
50
50
  min = DUMMY_LATENCY_NSEC
51
51
  MEASURE_ATTEMPT_COUNT.times do
@@ -55,13 +55,17 @@ class RedisClient
55
55
  min = duration if duration < min
56
56
  end
57
57
 
58
- latencies[node_key] = min
58
+ Thread.current.thread_variable_set(:latency, min)
59
59
  rescue StandardError
60
- latencies[node_key] = DUMMY_LATENCY_NSEC
60
+ Thread.current.thread_variable_set(:latency, DUMMY_LATENCY_NSEC)
61
61
  end
62
62
  end
63
63
 
64
- threads.each(&:join)
64
+ threads.each do |t|
65
+ t.join
66
+ latencies ||= {}
67
+ latencies[t.thread_variable_get(:node_key)] = t.thread_variable_get(:latency)
68
+ end
65
69
  end
66
70
 
67
71
  latencies
@@ -39,27 +39,36 @@ class RedisClient
39
39
  class << self
40
40
  def load_info(options, **kwargs) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
41
41
  startup_size = options.size > MAX_STARTUP_SAMPLE ? MAX_STARTUP_SAMPLE : options.size
42
- node_info_list = Array.new(startup_size)
43
- errors = Array.new(startup_size)
42
+ node_info_list = errors = nil
44
43
  startup_options = options.to_a.sample(MAX_STARTUP_SAMPLE).to_h
45
44
  startup_nodes = ::RedisClient::Cluster::Node.new(startup_options, **kwargs)
46
45
  startup_nodes.each_slice(MAX_THREADS).with_index do |chuncked_startup_nodes, chuncked_idx|
47
46
  threads = chuncked_startup_nodes.each_with_index.map do |raw_client, idx|
48
47
  Thread.new(raw_client, (MAX_THREADS * chuncked_idx) + idx) do |cli, i|
49
48
  Thread.pass
49
+ Thread.current.thread_variable_set(:index, i)
50
50
  reply = cli.call('CLUSTER', 'NODES')
51
- node_info_list[i] = parse_node_info(reply)
51
+ Thread.current.thread_variable_set(:info, parse_node_info(reply))
52
52
  rescue StandardError => e
53
- errors[i] = e
53
+ Thread.current.thread_variable_set(:error, e)
54
54
  ensure
55
55
  cli&.close
56
56
  end
57
57
  end
58
58
 
59
- threads.each(&:join)
59
+ threads.each do |t|
60
+ t.join
61
+ if t.thread_variable?(:info)
62
+ node_info_list ||= Array.new(startup_size)
63
+ node_info_list[t.thread_variable_get(:index)] = t.thread_variable_get(:info)
64
+ elsif t.thread_variable?(:error)
65
+ errors ||= Array.new(startup_size)
66
+ errors[t.thread_variable_get(:index)] = t.thread_variable_get(:error)
67
+ end
68
+ end
60
69
  end
61
70
 
62
- raise ::RedisClient::Cluster::InitialSetupError, errors if node_info_list.all?(&:nil?)
71
+ raise ::RedisClient::Cluster::InitialSetupError, errors if node_info_list.nil?
63
72
 
64
73
  grouped = node_info_list.compact.group_by do |rows|
65
74
  rows.sort_by { |row| row[:id] }
@@ -147,7 +156,7 @@ class RedisClient
147
156
 
148
157
  def send_ping(method, command, args, &block)
149
158
  result_values, errors = call_multiple_nodes(@topology.clients, method, command, args, &block)
150
- return result_values if errors.empty?
159
+ return result_values if errors.nil? || errors.empty?
151
160
 
152
161
  raise ReloadNeeded if errors.values.any?(::RedisClient::ConnectionError)
153
162
 
@@ -228,26 +237,35 @@ class RedisClient
228
237
 
229
238
  def call_multiple_nodes!(clients, method, command, args, &block)
230
239
  result_values, errors = call_multiple_nodes(clients, method, command, args, &block)
231
- return result_values if errors.empty?
240
+ return result_values if errors.nil? || errors.empty?
232
241
 
233
242
  raise ::RedisClient::Cluster::ErrorCollection, errors
234
243
  end
235
244
 
236
- def try_map(clients) # rubocop:disable Metrics/MethodLength
237
- results = {}
238
- errors = {}
245
+ def try_map(clients) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
246
+ results = errors = nil
239
247
  clients.each_slice(MAX_THREADS) do |chuncked_clients|
240
248
  threads = chuncked_clients.map do |k, v|
241
249
  Thread.new(k, v) do |node_key, client|
242
250
  Thread.pass
251
+ Thread.current.thread_variable_set(:node_key, node_key)
243
252
  reply = yield(node_key, client)
244
- results[node_key] = reply unless reply.nil?
253
+ Thread.current.thread_variable_set(:result, reply)
245
254
  rescue StandardError => e
246
- errors[node_key] = e
255
+ Thread.current.thread_variable_set(:error, e)
247
256
  end
248
257
  end
249
258
 
250
- threads.each(&:join)
259
+ threads.each do |t|
260
+ t.join
261
+ if t.thread_variable?(:result)
262
+ results ||= {}
263
+ results[t.thread_variable_get(:node_key)] = t.thread_variable_get(:result)
264
+ elsif t.thread_variable?(:error)
265
+ errors ||= {}
266
+ errors[t.thread_variable_get(:node_key)] = t.thread_variable_get(:error)
267
+ end
268
+ end
251
269
  end
252
270
 
253
271
  [results, errors]
@@ -20,37 +20,37 @@ class RedisClient
20
20
  def call(*args, **kwargs, &block)
21
21
  command = @command_builder.generate(args, kwargs)
22
22
  node_key = @router.find_node_key(command, seed: @seed)
23
- add_line(node_key, [@size, :call_v, command, block])
23
+ add_row(node_key, [@size, :call_v, command, block])
24
24
  end
25
25
 
26
26
  def call_v(args, &block)
27
27
  command = @command_builder.generate(args)
28
28
  node_key = @router.find_node_key(command, seed: @seed)
29
- add_line(node_key, [@size, :call_v, command, block])
29
+ add_row(node_key, [@size, :call_v, command, block])
30
30
  end
31
31
 
32
32
  def call_once(*args, **kwargs, &block)
33
33
  command = @command_builder.generate(args, kwargs)
34
34
  node_key = @router.find_node_key(command, seed: @seed)
35
- add_line(node_key, [@size, :call_once_v, command, block])
35
+ add_row(node_key, [@size, :call_once_v, command, block])
36
36
  end
37
37
 
38
38
  def call_once_v(args, &block)
39
39
  command = @command_builder.generate(args)
40
40
  node_key = @router.find_node_key(command, seed: @seed)
41
- add_line(node_key, [@size, :call_once_v, command, block])
41
+ add_row(node_key, [@size, :call_once_v, command, block])
42
42
  end
43
43
 
44
44
  def blocking_call(timeout, *args, **kwargs, &block)
45
45
  command = @command_builder.generate(args, kwargs)
46
46
  node_key = @router.find_node_key(command, seed: @seed)
47
- add_line(node_key, [@size, :blocking_call_v, timeout, command, block])
47
+ add_row(node_key, [@size, :blocking_call_v, timeout, command, block])
48
48
  end
49
49
 
50
50
  def blocking_call_v(timeout, args, &block)
51
51
  command = @command_builder.generate(args)
52
52
  node_key = @router.find_node_key(command, seed: @seed)
53
- add_line(node_key, [@size, :blocking_call_v, timeout, command, block])
53
+ add_row(node_key, [@size, :blocking_call_v, timeout, command, block])
54
54
  end
55
55
 
56
56
  def empty?
@@ -59,44 +59,57 @@ class RedisClient
59
59
 
60
60
  # TODO: https://github.com/redis-rb/redis-cluster-client/issues/37 handle redirections
61
61
  def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
62
- all_replies = Array.new(@size)
63
- errors = {}
62
+ all_replies = errors = nil
64
63
  @grouped.each_slice(MAX_THREADS) do |chuncked_grouped|
65
64
  threads = chuncked_grouped.map do |k, v|
66
65
  Thread.new(@router, k, v) do |router, node_key, rows|
67
66
  Thread.pass
68
- replies = router.find_node(node_key).pipelined do |pipeline|
69
- rows.each do |row|
70
- case row.size
71
- when 4 then pipeline.send(row[1], row[2], &row[3])
72
- when 5 then pipeline.send(row[1], row[2], row[3], &row[4])
73
- end
74
- end
75
- end
76
-
67
+ replies = do_pipelining(router.find_node(node_key), rows)
77
68
  raise ReplySizeError, "commands: #{rows.size}, replies: #{replies.size}" if rows.size != replies.size
78
69
 
79
- rows.each_with_index { |row, idx| all_replies[row.first] = replies[idx] }
70
+ Thread.current.thread_variable_set(:rows, rows)
71
+ Thread.current.thread_variable_set(:replies, replies)
80
72
  rescue StandardError => e
81
- errors[node_key] = e
73
+ Thread.current.thread_variable_set(:node_key, node_key)
74
+ Thread.current.thread_variable_set(:error, e)
82
75
  end
83
76
  end
84
77
 
85
- threads.each(&:join)
78
+ threads.each do |t|
79
+ t.join
80
+ if t.thread_variable?(:replies)
81
+ all_replies ||= Array.new(@size)
82
+ t.thread_variable_get(:rows).each_with_index { |r, i| all_replies[r.first] = t.thread_variable_get(:replies)[i] }
83
+ elsif t.thread_variable?(:error)
84
+ errors ||= {}
85
+ errors[t.thread_variable_get(:node_key)] = t.thread_variable_get(:error)
86
+ end
87
+ end
86
88
  end
87
89
 
88
- return all_replies if errors.empty?
90
+ return all_replies if errors.nil?
89
91
 
90
92
  raise ::RedisClient::Cluster::ErrorCollection, errors
91
93
  end
92
94
 
93
95
  private
94
96
 
95
- def add_line(node_key, line)
97
+ def add_row(node_key, row)
96
98
  @grouped[node_key] = [] unless @grouped.key?(node_key)
97
- @grouped[node_key] << line
99
+ @grouped[node_key] << row
98
100
  @size += 1
99
101
  end
102
+
103
+ def do_pipelining(node, rows)
104
+ node.pipelined do |pipeline|
105
+ rows.each do |row|
106
+ case row.size
107
+ when 4 then pipeline.send(row[1], row[2], &row[3])
108
+ when 5 then pipeline.send(row[1], row[2], row[3], &row[4])
109
+ end
110
+ end
111
+ end
112
+ end
100
113
  end
101
114
  end
102
115
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-cluster-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taishi Kasuga
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-19 00:00:00.000000000 Z
11
+ date: 2022-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client