redis-cluster-client 0.1.0 → 0.2.0

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: 367df4e02bcd425f14da73b2ff243dfdb7fd44c6cb565bcc46952b939057904f
4
- data.tar.gz: bfdb8033d0695fe0389563ad563c8445f9624e99ef6315e7374ee7f2e440fe40
3
+ metadata.gz: 5160c83d23cb638fc76cf079377981d6778560ba0eb476da03f58d6f4eded9af
4
+ data.tar.gz: dd0baec0d24de14e2cba10c4ea3f45af7f1bef2db30f609c9551ed2d13c0bf4a
5
5
  SHA512:
6
- metadata.gz: 278740e8829a1def72a411552ed7c17d0d265930c81dfc2b967cfa325a74cdbdbd0adb832dacc77e4c86c8316648695b94044cb6fdf3dd3267617d5f18b95ec1
7
- data.tar.gz: 007bf587198b7575dabee128c0500700ef0d10c7b699a632023ce4d80fa788d2a88e851748f041ab5f6453350d7de6f9d8c96bcbc798deec7acbf37b2700ea6a
6
+ metadata.gz: 1cf5c16776bb7ff4c53ffa66e3de3371c1130fed7a4916982e7fba9859ba9ae7505af0bc5e8e02b58f22d116ab74692a4572d835f05672457bac4ddd469e3162
7
+ data.tar.gz: f08215c00f2b12b00247604917a7f7abc228ddd0e4305c67af38f8e2087a8b3785a22bfbd09ac32f75789719a624be49663f5048f6187318477069e4ef9627a1
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'redis_cluster_client'
@@ -128,9 +128,9 @@ class RedisClient
128
128
  @clients.fetch(node_key)
129
129
  end
130
130
 
131
- def call_all(method, *args, **kwargs, &block)
131
+ def call_all(method, command, args, &block)
132
132
  results, errors = try_map do |_, client|
133
- client.send(method, *args, **kwargs, &block)
133
+ client.send(method, *args, command, &block)
134
134
  end
135
135
 
136
136
  return results.values if errors.empty?
@@ -138,11 +138,11 @@ class RedisClient
138
138
  raise ::RedisClient::Cluster::ErrorCollection, errors
139
139
  end
140
140
 
141
- def call_primaries(method, *args, **kwargs, &block)
141
+ def call_primaries(method, command, args, &block)
142
142
  results, errors = try_map do |node_key, client|
143
143
  next if replica?(node_key)
144
144
 
145
- client.send(method, *args, **kwargs, &block)
145
+ client.send(method, *args, command, &block)
146
146
  end
147
147
 
148
148
  return results.values if errors.empty?
@@ -150,14 +150,14 @@ class RedisClient
150
150
  raise ::RedisClient::Cluster::ErrorCollection, errors
151
151
  end
152
152
 
153
- def call_replicas(method, *args, **kwargs, &block)
154
- return call_primaries(method, *args, **kwargs, &block) if replica_disabled?
153
+ def call_replicas(method, command, args, &block)
154
+ return call_primaries(method, command, args, &block) if replica_disabled?
155
155
 
156
156
  replica_node_keys = @replications.values.map(&:sample)
157
157
  results, errors = try_map do |node_key, client|
158
158
  next if primary?(node_key) || !replica_node_keys.include?(node_key)
159
159
 
160
- client.send(method, *args, **kwargs, &block)
160
+ client.send(method, *args, command, &block)
161
161
  end
162
162
 
163
163
  return results.values if errors.empty?
@@ -165,9 +165,9 @@ class RedisClient
165
165
  raise ::RedisClient::Cluster::ErrorCollection, errors
166
166
  end
167
167
 
168
- def send_ping(method, *args, **kwargs, &block)
168
+ def send_ping(method, command, args, &block)
169
169
  results, errors = try_map do |_, client|
170
- client.send(method, *args, **kwargs, &block)
170
+ client.send(method, *args, command, &block)
171
171
  end
172
172
 
173
173
  return results.values if errors.empty?
@@ -8,27 +8,52 @@ class RedisClient
8
8
  class Pipeline
9
9
  ReplySizeError = Class.new(::RedisClient::Error)
10
10
 
11
- def initialize(router)
11
+ def initialize(router, command_builder)
12
12
  @router = router
13
+ @command_builder = command_builder
13
14
  @grouped = Hash.new([].freeze)
14
15
  @size = 0
15
16
  end
16
17
 
17
- def call(*command, **kwargs)
18
- node_key = @router.find_node_key(*command, primary_only: true, **kwargs)
19
- @grouped[node_key] += [[@size, :call, command, kwargs]]
18
+ def call(*args, **kwargs, &block)
19
+ command = @command_builder.generate(args, kwargs)
20
+ node_key = @router.find_node_key(command, primary_only: true)
21
+ @grouped[node_key] += [[@size, :call_v, command, block]]
20
22
  @size += 1
21
23
  end
22
24
 
23
- def call_once(*command, **kwargs)
24
- node_key = @router.find_node_key(*command, primary_only: true, **kwargs)
25
- @grouped[node_key] += [[@size, :call_once, command, kwargs]]
25
+ def call_v(args, &block)
26
+ command = @command_builder.generate(args)
27
+ node_key = @router.find_node_key(command, primary_only: true)
28
+ @grouped[node_key] += [[@size, :call_v, command, block]]
26
29
  @size += 1
27
30
  end
28
31
 
29
- def blocking_call(timeout, *command, **kwargs)
30
- node_key = @router.find_node_key(*command, primary_only: true, **kwargs)
31
- @grouped[node_key] += [[@size, :blocking_call, timeout, command, kwargs]]
32
+ def call_once(*args, **kwargs, &block)
33
+ command = @command_builder.generate(args, kwargs)
34
+ node_key = @router.find_node_key(command, primary_only: true)
35
+ @grouped[node_key] += [[@size, :call_once_v, command, block]]
36
+ @size += 1
37
+ end
38
+
39
+ def call_once_v(args, &block)
40
+ command = @command_builder.generate(args)
41
+ node_key = @router.find_node_key(command, primary_only: true)
42
+ @grouped[node_key] += [[@size, :call_once_v, command, block]]
43
+ @size += 1
44
+ end
45
+
46
+ def blocking_call(timeout, *args, **kwargs, &block)
47
+ command = @command_builder.generate(args, kwargs)
48
+ node_key = @router.find_node_key(command, primary_only: true)
49
+ @grouped[node_key] += [[@size, :blocking_call_v, timeout, command, block]]
50
+ @size += 1
51
+ end
52
+
53
+ def blocking_call_v(timeout, args, &block)
54
+ command = @command_builder.generate(args)
55
+ node_key = @router.find_node_key(command, primary_only: true)
56
+ @grouped[node_key] += [[@size, :blocking_call_v, timeout, command, block]]
32
57
  @size += 1
33
58
  end
34
59
 
@@ -37,20 +62,15 @@ class RedisClient
37
62
  end
38
63
 
39
64
  # TODO: https://github.com/redis-rb/redis-cluster-client/issues/37 handle redirections
40
- def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
65
+ def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
41
66
  all_replies = Array.new(@size)
42
67
  errors = {}
43
68
  threads = @grouped.map do |k, v|
44
69
  Thread.new(@router, k, v) do |router, node_key, rows|
45
70
  Thread.pass
46
71
  replies = router.find_node(node_key).pipelined do |pipeline|
47
- rows.each do |row|
48
- case row[1]
49
- when :call then pipeline.call(*row[2], **row[3])
50
- when :call_once then pipeline.call_once(*row[2], **row[3])
51
- when :blocking_call then pipeline.blocking_call(row[2], *row[3], **row[4])
52
- else raise NotImplementedError, row[1]
53
- end
72
+ rows.each do |(_size, *row, block)|
73
+ pipeline.send(*row, &block)
54
74
  end
55
75
  end
56
76
 
@@ -3,15 +3,24 @@
3
3
  class RedisClient
4
4
  class Cluster
5
5
  class PubSub
6
- def initialize(router)
6
+ def initialize(router, command_builder)
7
7
  @router = router
8
+ @command_builder = command_builder
8
9
  @pubsub = nil
9
10
  end
10
11
 
11
- def call(*command, **kwargs)
12
+ def call(*args, **kwargs)
12
13
  close
13
- @pubsub = @router.assign_node(*command, **kwargs).pubsub
14
- @pubsub.call(*command, **kwargs)
14
+ command = @command_builder.generate(args, kwargs)
15
+ @pubsub = @router.assign_node(command).pubsub
16
+ @pubsub.call_v(command)
17
+ end
18
+
19
+ def call_v(command)
20
+ close
21
+ command = @command_builder.generate(command)
22
+ @pubsub = @router.assign_node(command).pubsub
23
+ @pubsub.call_v(command)
15
24
  end
16
25
 
17
26
  def close
@@ -20,40 +20,37 @@ class RedisClient
20
20
  @client_kwargs = kwargs
21
21
  @node = fetch_cluster_info(@config, pool: @pool, **@client_kwargs)
22
22
  @command = ::RedisClient::Cluster::Command.load(@node)
23
- @command_builder = @config.command_builder
24
23
  @mutex = Mutex.new
24
+ @command_builder = @config.command_builder
25
25
  end
26
26
 
27
- def send_command(method, *args, **kwargs, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
28
- command = method == :blocking_call && args.size > 1 ? args[1..] : args
29
- command = @command_builder.generate!(command, kwargs)
30
-
27
+ def send_command(method, command, *args, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
31
28
  cmd = command.first.to_s.downcase
32
29
  case cmd
33
30
  when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
34
- @node.call_all(method, *args, **kwargs, &block).first
31
+ @node.call_all(method, command, args, &block).first
35
32
  when 'flushall', 'flushdb'
36
- @node.call_primaries(method, *args, **kwargs, &block).first
37
- when 'ping' then @node.send_ping(method, *args, **kwargs, &block).first
38
- when 'wait' then send_wait_command(method, *args, **kwargs, &block)
39
- when 'keys' then @node.call_replicas(method, *args, **kwargs, &block).flatten.sort_by(&:to_s)
40
- when 'dbsize' then @node.call_replicas(method, *args, **kwargs, &block).select { |e| e.is_a?(Integer) }.sum
41
- when 'scan' then scan(*command, **kwargs)
42
- when 'lastsave' then @node.call_all(method, *args, **kwargs, &block).sort_by(&:to_i)
43
- when 'role' then @node.call_all(method, *args, **kwargs, &block)
44
- when 'config' then send_config_command(method, *args, **kwargs, &block)
45
- when 'client' then send_client_command(method, *args, **kwargs, &block)
46
- when 'cluster' then send_cluster_command(method, *args, **kwargs, &block)
33
+ @node.call_primaries(method, command, args, &block).first
34
+ when 'ping' then @node.send_ping(method, command, args, &block).first
35
+ when 'wait' then send_wait_command(method, command, args, &block)
36
+ when 'keys' then @node.call_replicas(method, command, args, &block).flatten.sort_by(&:to_s)
37
+ when 'dbsize' then @node.call_replicas(method, command, args, &block).select { |e| e.is_a?(Integer) }.sum
38
+ when 'scan' then scan(command)
39
+ when 'lastsave' then @node.call_all(method, command, args, &block).sort_by(&:to_i)
40
+ when 'role' then @node.call_all(method, command, args, &block)
41
+ when 'config' then send_config_command(method, command, args, &block)
42
+ when 'client' then send_client_command(method, command, args, &block)
43
+ when 'cluster' then send_cluster_command(method, command, args, &block)
47
44
  when 'readonly', 'readwrite', 'shutdown'
48
45
  raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, cmd
49
- when 'memory' then send_memory_command(method, *args, **kwargs, &block)
50
- when 'script' then send_script_command(method, *args, **kwargs, &block)
51
- when 'pubsub' then send_pubsub_command(method, *args, **kwargs, &block)
46
+ when 'memory' then send_memory_command(method, command, args, &block)
47
+ when 'script' then send_script_command(method, command, args, &block)
48
+ when 'pubsub' then send_pubsub_command(method, command, args, &block)
52
49
  when 'discard', 'exec', 'multi', 'unwatch'
53
50
  raise ::RedisClient::Cluster::AmbiguousNodeError, cmd
54
51
  else
55
- node = assign_node(*command)
56
- try_send(node, method, *args, **kwargs, &block)
52
+ node = assign_node(command)
53
+ try_send(node, method, command, args, &block)
57
54
  end
58
55
  rescue ::RedisClient::Cluster::Node::ReloadNeeded
59
56
  update_cluster_info!
@@ -67,7 +64,37 @@ class RedisClient
67
64
 
68
65
  # @see https://redis.io/topics/cluster-spec#redirection-and-resharding
69
66
  # Redirection and resharding
70
- def try_send(node, method, *args, retry_count: 3, **kwargs, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
67
+ def try_send(node, method, command, args, retry_count: 3, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
68
+ node.send(method, *args, command, &block)
69
+ rescue ::RedisClient::CommandError => e
70
+ raise if retry_count <= 0
71
+
72
+ if e.message.start_with?('MOVED')
73
+ node = assign_redirection_node(e.message)
74
+ retry_count -= 1
75
+ retry
76
+ elsif e.message.start_with?('ASK')
77
+ node = assign_asking_node(e.message)
78
+ node.call('ASKING')
79
+ retry_count -= 1
80
+ retry
81
+ elsif e.message.start_with?('CLUSTERDOWN Hash slot not served')
82
+ update_cluster_info!
83
+ retry_count -= 1
84
+ retry
85
+ else
86
+ raise
87
+ end
88
+ rescue ::RedisClient::ConnectionError => e
89
+ raise if method == :blocking_call_v || (method == :blocking_call && e.is_a?(RedisClient::ReadTimeoutError))
90
+ raise if retry_count <= 0
91
+
92
+ update_cluster_info!
93
+ retry_count -= 1
94
+ retry
95
+ end
96
+
97
+ def try_delegate(node, method, *args, retry_count: 3, **kwargs, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
71
98
  node.send(method, *args, **kwargs, &block)
72
99
  rescue ::RedisClient::CommandError => e
73
100
  raise if retry_count <= 0
@@ -97,7 +124,7 @@ class RedisClient
97
124
  end
98
125
 
99
126
  def scan(*command, **kwargs) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
100
- command = @command_builder.generate!(command, kwargs)
127
+ command = @command_builder.generate(command, kwargs)
101
128
 
102
129
  command[1] = ZERO_CURSOR_FOR_SCAN if command.size == 1
103
130
  input_cursor = Integer(command[1])
@@ -112,7 +139,7 @@ class RedisClient
112
139
 
113
140
  command[1] = raw_cursor.to_s
114
141
 
115
- result_cursor, result_keys = client.call(*command, **kwargs)
142
+ result_cursor, result_keys = client.call_v(command)
116
143
  result_cursor = Integer(result_cursor)
117
144
 
118
145
  client_index += 1 if result_cursor == 0
@@ -120,14 +147,12 @@ class RedisClient
120
147
  [((result_cursor << 8) + client_index).to_s, result_keys]
121
148
  end
122
149
 
123
- def assign_node(*command, **kwargs)
124
- node_key = find_node_key(*command, **kwargs)
150
+ def assign_node(command, primary_only: false)
151
+ node_key = find_node_key(command, primary_only: primary_only)
125
152
  find_node(node_key)
126
153
  end
127
154
 
128
- def find_node_key(*command, primary_only: false, **kwargs)
129
- command = @command_builder.generate!(command, kwargs)
130
-
155
+ def find_node_key(command, primary_only: false)
131
156
  key = @command.extract_first_key(command)
132
157
  slot = key.empty? ? nil : ::RedisClient::Cluster::KeySlotConverter.convert(key)
133
158
 
@@ -154,8 +179,8 @@ class RedisClient
154
179
 
155
180
  private
156
181
 
157
- def send_wait_command(method, *args, retry_count: 3, **kwargs, &block)
158
- @node.call_primaries(method, *args, **kwargs, &block).select { |r| r.is_a?(Integer) }.sum
182
+ def send_wait_command(method, command, args, retry_count: 3, &block)
183
+ @node.call_primaries(method, command, args, &block).select { |r| r.is_a?(Integer) }.sum
159
184
  rescue ::RedisClient::Cluster::ErrorCollection => e
160
185
  raise if retry_count <= 0
161
186
  raise if e.errors.values.none? do |err|
@@ -167,82 +192,65 @@ class RedisClient
167
192
  retry
168
193
  end
169
194
 
170
- def send_config_command(method, *args, **kwargs, &block)
171
- command = method == :blocking_call && args.size > 1 ? args[1..] : args
172
- command = @command_builder.generate!(command, kwargs)
173
-
195
+ def send_config_command(method, command, args, &block)
174
196
  case command[1].to_s.downcase
175
197
  when 'resetstat', 'rewrite', 'set'
176
- @node.call_all(method, *args, **kwargs, &block).first
177
- else assign_node(*command).send(method, *args, **kwargs, &block)
198
+ @node.call_all(method, command, args, &block).first
199
+ else assign_node(command).send(method, *args, command, &block)
178
200
  end
179
201
  end
180
202
 
181
- def send_memory_command(method, *args, **kwargs, &block)
182
- command = method == :blocking_call && args.size > 1 ? args[1..] : args
183
- command = @command_builder.generate!(command, kwargs)
184
-
203
+ def send_memory_command(method, command, args, &block)
185
204
  case command[1].to_s.downcase
186
- when 'stats' then @node.call_all(method, *args, **kwargs, &block)
187
- when 'purge' then @node.call_all(method, *args, **kwargs, &block).first
188
- else assign_node(*command).send(method, *args, **kwargs, &block)
205
+ when 'stats' then @node.call_all(method, command, args, &block)
206
+ when 'purge' then @node.call_all(method, command, args, &block).first
207
+ else assign_node(command).send(method, *args, command, &block)
189
208
  end
190
209
  end
191
210
 
192
- def send_client_command(method, *args, **kwargs, &block)
193
- command = method == :blocking_call && args.size > 1 ? args[1..] : args
194
- command = @command_builder.generate!(command, kwargs)
195
-
211
+ def send_client_command(method, command, args, &block)
196
212
  case command[1].to_s.downcase
197
- when 'list' then @node.call_all(method, *args, **kwargs, &block).flatten
213
+ when 'list' then @node.call_all(method, command, args, &block).flatten
198
214
  when 'pause', 'reply', 'setname'
199
- @node.call_all(method, *args, **kwargs, &block).first
200
- else assign_node(*command).send(method, *args, **kwargs, &block)
215
+ @node.call_all(method, command, args, &block).first
216
+ else assign_node(command).send(method, *args, command, &block)
201
217
  end
202
218
  end
203
219
 
204
- def send_cluster_command(method, *args, **kwargs, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
205
- command = method == :blocking_call && args.size > 1 ? args[1..] : args
206
- command = @command_builder.generate!(command, kwargs)
220
+ def send_cluster_command(method, command, args, &block) # rubocop:disable Metrics/MethodLength
207
221
  subcommand = command[1].to_s.downcase
208
222
 
209
223
  case subcommand
210
224
  when 'addslots', 'delslots', 'failover', 'forget', 'meet', 'replicate',
211
225
  'reset', 'set-config-epoch', 'setslot'
212
226
  raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, ['cluster', subcommand]
213
- when 'saveconfig' then @node.call_all(method, *args, **kwargs, &block).first
227
+ when 'saveconfig' then @node.call_all(method, command, args, &block).first
214
228
  when 'getkeysinslot'
215
229
  raise ArgumentError, command.join(' ') if command.size != 4
216
230
 
217
- find_node(@node.find_node_key_of_replica(command[2])).send(method, *args, **kwargs, &block)
218
- else assign_node(*command).send(method, *args, **kwargs, &block)
231
+ find_node(@node.find_node_key_of_replica(command[2])).send(method, *args, command, &block)
232
+ else assign_node(command).send(method, *args, command, &block)
219
233
  end
220
234
  end
221
235
 
222
- def send_script_command(method, *args, **kwargs, &block)
223
- command = method == :blocking_call && args.size > 1 ? args[1..] : args
224
- command = @command_builder.generate!(command, kwargs)
225
-
236
+ def send_script_command(method, command, args, &block)
226
237
  case command[1].to_s.downcase
227
238
  when 'debug', 'kill'
228
- @node.call_all(method, *args, **kwargs, &block).first
239
+ @node.call_all(method, command, args, &block).first
229
240
  when 'flush', 'load'
230
- @node.call_primaries(method, *args, **kwargs, &block).first
231
- else assign_node(*command).send(method, *args, **kwargs, &block)
241
+ @node.call_primaries(method, command, args, &block).first
242
+ else assign_node(command).send(method, *args, command, &block)
232
243
  end
233
244
  end
234
245
 
235
- def send_pubsub_command(method, *args, **kwargs, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
236
- command = method == :blocking_call && args.size > 1 ? args[1..] : args
237
- command = @command_builder.generate!(command, kwargs)
238
-
246
+ def send_pubsub_command(method, command, args, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
239
247
  case command[1].to_s.downcase
240
- when 'channels' then @node.call_all(method, *args, **kwargs, &block).flatten.uniq.sort_by(&:to_s)
248
+ when 'channels' then @node.call_all(method, command, args, &block).flatten.uniq.sort_by(&:to_s)
241
249
  when 'numsub'
242
- @node.call_all(method, *args, **kwargs, &block).reject(&:empty?).map { |e| Hash[*e] }
250
+ @node.call_all(method, command, args, &block).reject(&:empty?).map { |e| Hash[*e] }
243
251
  .reduce({}) { |a, e| a.merge(e) { |_, v1, v2| v1 + v2 } }
244
- when 'numpat' then @node.call_all(method, *args, **kwargs, &block).select { |e| e.is_a?(Integer) }.sum
245
- else assign_node(*command).send(method, *args, **kwargs, &block)
252
+ when 'numpat' then @node.call_all(method, command, args, &block).select { |e| e.is_a?(Integer) }.sum
253
+ else assign_node(command).send(method, *args, command, &block)
246
254
  end
247
255
  end
248
256
 
@@ -269,7 +277,7 @@ class RedisClient
269
277
  def update_cluster_info!
270
278
  @mutex.synchronize do
271
279
  begin
272
- @node.call_all(:close)
280
+ @node.each(&:close)
273
281
  rescue ::RedisClient::Cluster::ErrorCollection
274
282
  # ignore
275
283
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'redis_client'
4
3
  require 'redis_client/cluster/pipeline'
5
4
  require 'redis_client/cluster/pub_sub'
6
5
  require 'redis_client/cluster/router'
@@ -9,24 +8,46 @@ class RedisClient
9
8
  class Cluster
10
9
  ZERO_CURSOR_FOR_SCAN = '0'
11
10
 
11
+ attr_reader :config
12
+
12
13
  def initialize(config, pool: nil, **kwargs)
14
+ @config = config
13
15
  @router = ::RedisClient::Cluster::Router.new(config, pool: pool, **kwargs)
16
+ @command_builder = config.command_builder
14
17
  end
15
18
 
16
19
  def inspect
17
20
  "#<#{self.class.name} #{@router.node.node_keys.join(', ')}>"
18
21
  end
19
22
 
20
- def call(*command, **kwargs, &block)
21
- @router.send_command(:call, *command, **kwargs, &block)
23
+ def call(*args, **kwargs, &block)
24
+ command = @command_builder.generate(args, kwargs)
25
+ @router.send_command(:call_v, command, &block)
26
+ end
27
+
28
+ def call_v(command, &block)
29
+ command = @command_builder.generate(command)
30
+ @router.send_command(:call_v, command, &block)
31
+ end
32
+
33
+ def call_once(*args, **kwargs, &block)
34
+ command = @command_builder.generate(args, kwargs)
35
+ @router.send_command(:call_once_v, command, &block)
36
+ end
37
+
38
+ def call_once_v(command, &block)
39
+ command = @command_builder.generate(command)
40
+ @router.send_command(:call_once_v, command, &block)
22
41
  end
23
42
 
24
- def call_once(*command, **kwargs, &block)
25
- @router.send_command(:call_once, *command, **kwargs, &block)
43
+ def blocking_call(timeout, *args, **kwargs, &block)
44
+ command = @command_builder.generate(args, kwargs)
45
+ @router.send_command(:blocking_call_v, command, timeout, &block)
26
46
  end
27
47
 
28
- def blocking_call(timeout, *command, **kwargs, &block)
29
- @router.send_command(:blocking_call, timeout, *command, **kwargs, &block)
48
+ def blocking_call_v(timeout, command, &block)
49
+ command = @command_builder.generate(command)
50
+ @router.send_command(:blocking_call_v, command, timeout, &block)
30
51
  end
31
52
 
32
53
  def scan(*args, **kwargs, &block)
@@ -41,22 +62,22 @@ class RedisClient
41
62
  end
42
63
 
43
64
  def sscan(key, *args, **kwargs, &block)
44
- node = @router.assign_node('SSCAN', key)
45
- @router.try_send(node, :sscan, key, *args, **kwargs, &block)
65
+ node = @router.assign_node(['SSCAN', key])
66
+ @router.try_delegate(node, :sscan, key, *args, **kwargs, &block)
46
67
  end
47
68
 
48
69
  def hscan(key, *args, **kwargs, &block)
49
- node = @router.assign_node('HSCAN', key)
50
- @router.try_send(node, :hscan, key, *args, **kwargs, &block)
70
+ node = @router.assign_node(['HSCAN', key])
71
+ @router.try_delegate(node, :hscan, key, *args, **kwargs, &block)
51
72
  end
52
73
 
53
74
  def zscan(key, *args, **kwargs, &block)
54
- node = @router.assign_node('ZSCAN', key)
55
- @router.try_send(node, :zscan, key, *args, **kwargs, &block)
75
+ node = @router.assign_node(['ZSCAN', key])
76
+ @router.try_delegate(node, :zscan, key, *args, **kwargs, &block)
56
77
  end
57
78
 
58
79
  def pipelined
59
- pipeline = ::RedisClient::Cluster::Pipeline.new(@router)
80
+ pipeline = ::RedisClient::Cluster::Pipeline.new(@router, @command_builder)
60
81
  yield pipeline
61
82
  return [] if pipeline.empty? == 0
62
83
 
@@ -64,11 +85,11 @@ class RedisClient
64
85
  end
65
86
 
66
87
  def pubsub
67
- ::RedisClient::Cluster::PubSub.new(@router)
88
+ ::RedisClient::Cluster::PubSub.new(@router, @command_builder)
68
89
  end
69
90
 
70
91
  def close
71
- @router.node.call_all(:close)
92
+ @router.node.each(&:close)
72
93
  nil
73
94
  end
74
95
 
@@ -77,7 +98,8 @@ class RedisClient
77
98
  def method_missing(name, *args, **kwargs, &block)
78
99
  if @router.command_exists?(name)
79
100
  args.unshift(name)
80
- return @router.send_command(:call, *args, **kwargs, &block)
101
+ command = @command_builder.generate(args, kwargs)
102
+ return @router.send_command(:call_v, command, &block)
81
103
  end
82
104
 
83
105
  super
@@ -20,15 +20,16 @@ class RedisClient
20
20
 
21
21
  InvalidClientConfigError = Class.new(::RedisClient::Error)
22
22
 
23
- attr_reader :command_builder
23
+ attr_reader :command_builder, :client_config
24
24
 
25
- def initialize(nodes: DEFAULT_NODES, replica: false, fixed_hostname: '', **client_config)
25
+ def initialize(nodes: DEFAULT_NODES, replica: false, client_implementation: Cluster, fixed_hostname: '', **client_config)
26
26
  @replica = true & replica
27
27
  @fixed_hostname = fixed_hostname.to_s
28
28
  @node_configs = build_node_configs(nodes.dup)
29
29
  client_config = client_config.reject { |k, _| IGNORE_GENERIC_CONFIG_KEYS.include?(k) }
30
30
  @command_builder = client_config.fetch(:command_builder, ::RedisClient::CommandBuilder)
31
31
  @client_config = merge_generic_config(client_config, @node_configs)
32
+ @client_implementation = client_implementation
32
33
  @mutex = Mutex.new
33
34
  end
34
35
 
@@ -36,12 +37,16 @@ class RedisClient
36
37
  "#<#{self.class.name} #{per_node_key.values}>"
37
38
  end
38
39
 
40
+ def read_timeout
41
+ @client_config[:read_timeout] || @client_config[:timeout] || RedisClient::Config::DEFAULT_TIMEOUT
42
+ end
43
+
39
44
  def new_pool(size: 5, timeout: 5, **kwargs)
40
- ::RedisClient::Cluster.new(self, pool: { size: size, timeout: timeout }, **kwargs)
45
+ @client_implementation.new(self, pool: { size: size, timeout: timeout }, **kwargs)
41
46
  end
42
47
 
43
48
  def new_client(**kwargs)
44
- ::RedisClient::Cluster.new(self, **kwargs)
49
+ @client_implementation.new(self, **kwargs)
45
50
  end
46
51
 
47
52
  def per_node_key
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.1.0
4
+ version: 0.2.0
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-07-02 00:00:00.000000000 Z
11
+ date: 2022-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.5'
19
+ version: '0.6'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.5'
26
+ version: '0.6'
27
27
  description:
28
28
  email:
29
29
  - proxy0721@gmail.com
@@ -31,6 +31,7 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
+ - lib/redis-cluster-client.rb
34
35
  - lib/redis_client/cluster.rb
35
36
  - lib/redis_client/cluster/command.rb
36
37
  - lib/redis_client/cluster/errors.rb