redis-cluster-client 0.1.0 → 0.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 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