redis-cluster-client 0.3.3 → 0.3.4

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: 1eaec04db89e1afa8a1d0a27688194d5941a94edb00aef979b1f368d01b4dd41
4
- data.tar.gz: 36571e86def197fc3633d4c026958fbe635576d5f9aec3ab19b32759957a8f14
3
+ metadata.gz: 458c3d9cc4d1f6595510663cede0403953b2555ace0d3cae814663b23f69f1cb
4
+ data.tar.gz: 01d2a34641e298ff7e99cc5f9edbad4ed152e5ca4f18e16181b9a4b84a2492c2
5
5
  SHA512:
6
- metadata.gz: 2da9f21f30cc49f9df64cf11ed5ee3c0385bc6310bbb7e8cf3478552272f716ab68928aee05bb90b24d39253040f170fd38df78687afb78ea612f310f6a96b2e
7
- data.tar.gz: 4f7828b8072f01aaa5aa56264d7fda6f8d4ff17bce7a88a5adb2c05bd5eab8a74fe137b3c59ce1bba086a9793a05d490252d0df94228e35c6c10a2b0d869d797
6
+ metadata.gz: 3680e6b8b1594001060eb2dea29eb60f0779bba6a43350246b1d5c7e47b1bb1e04a6e1188ac87c1228adac21e86347cb3820679d6c92b693d7f7fedabba88402
7
+ data.tar.gz: 21927b8a14e9ad075e3808e736789c4339af907f5d99e16806273f1553c505e7fc86faabfa067b98f2a3dd7d45a41fb0f89e780e08825aa9df4317531871da5d
@@ -2,10 +2,13 @@
2
2
 
3
3
  require 'redis_client'
4
4
  require 'redis_client/cluster/errors'
5
+ require 'redis_client/cluster/normalized_cmd_name'
5
6
 
6
7
  class RedisClient
7
8
  class Cluster
8
9
  class Command
10
+ EMPTY_STRING = ''
11
+
9
12
  class << self
10
13
  def load(nodes) # rubocop:disable Metrics/MethodLength
11
14
  errors = []
@@ -29,7 +32,10 @@ class RedisClient
29
32
 
30
33
  def parse_command_details(rows)
31
34
  rows&.reject { |row| row[0].nil? }.to_h do |row|
32
- [row[0].downcase, { arity: row[1], flags: row[2], first: row[3], last: row[4], step: row[5] }]
35
+ [
36
+ ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_name(row[0]),
37
+ { arity: row[1], flags: row[2], first: row[3], last: row[4], step: row[5] }
38
+ ]
33
39
  end
34
40
  end
35
41
  end
@@ -40,7 +46,7 @@ class RedisClient
40
46
 
41
47
  def extract_first_key(command)
42
48
  i = determine_first_key_position(command)
43
- return '' if i == 0
49
+ return EMPTY_STRING if i == 0
44
50
 
45
51
  key = (command[i].is_a?(Array) ? command[i].flatten.first : command[i]).to_s
46
52
  hash_tag = extract_hash_tag(key)
@@ -56,7 +62,8 @@ class RedisClient
56
62
  end
57
63
 
58
64
  def exists?(name)
59
- @details.key?(name.to_s.downcase)
65
+ key = ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_name(name)
66
+ @details.key?(key)
60
67
  end
61
68
 
62
69
  private
@@ -72,14 +79,14 @@ class RedisClient
72
79
  end
73
80
 
74
81
  def dig_details(command, key)
75
- name = command&.flatten&.first.to_s.downcase # OPTIMIZE: prevent allocation for string
82
+ name = ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_command(command)
76
83
  return if name.empty? || !@details.key?(name)
77
84
 
78
85
  @details.fetch(name).fetch(key)
79
86
  end
80
87
 
81
88
  def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
82
- case command&.flatten&.first.to_s.downcase # OPTIMIZE: prevent allocation for string
89
+ case ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_command(command)
83
90
  when 'eval', 'evalsha', 'zinterstore', 'zunionstore' then 3
84
91
  when 'object' then 2
85
92
  when 'memory'
@@ -104,7 +111,7 @@ class RedisClient
104
111
  s = key.index('{')
105
112
  e = key.index('}', s.to_i + 1)
106
113
 
107
- return '' if s.nil? || e.nil?
114
+ return EMPTY_STRING if s.nil? || e.nil?
108
115
 
109
116
  key[s + 1..e - 1]
110
117
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+
5
+ class RedisClient
6
+ class Cluster
7
+ class NormalizedCmdName
8
+ include Singleton
9
+
10
+ EMPTY_STRING = ''
11
+
12
+ def initialize
13
+ @cache = {}
14
+ @mutex = Mutex.new
15
+ end
16
+
17
+ def get_by_command(command)
18
+ get(command, index: 0)
19
+ end
20
+
21
+ def get_by_subcommand(command)
22
+ get(command, index: 1)
23
+ end
24
+
25
+ def get_by_name(name)
26
+ get(name, index: 0)
27
+ end
28
+
29
+ def clear
30
+ @mutex.synchronize { @cache.clear }
31
+ end
32
+
33
+ private
34
+
35
+ def get(command, index:)
36
+ name = extract_name(command, index: index)
37
+ return EMPTY_STRING if name.nil? || name.empty?
38
+
39
+ normalize(name)
40
+ end
41
+
42
+ def extract_name(command, index:)
43
+ case command
44
+ when String, Symbol then index.zero? ? command : nil
45
+ when Array then extract_name_from_array(command, index: index)
46
+ end
47
+ end
48
+
49
+ def extract_name_from_array(command, index:)
50
+ return if command.size - 1 < index
51
+
52
+ case e = command[index]
53
+ when String, Symbol then e
54
+ when Array then e[index]
55
+ end
56
+ end
57
+
58
+ def normalize(name)
59
+ return @cache[name] if @cache.key?(name)
60
+ return name.to_s.downcase if @mutex.locked?
61
+
62
+ @mutex.synchronize { @cache[name] = name.to_s.downcase }
63
+ @cache[name]
64
+ end
65
+ end
66
+ end
67
+ end
@@ -66,8 +66,11 @@ class RedisClient
66
66
  Thread.new(@router, k, v) do |router, node_key, rows|
67
67
  Thread.pass
68
68
  replies = router.find_node(node_key).pipelined do |pipeline|
69
- rows.each do |(_size, *row, block)|
70
- pipeline.send(*row, &block)
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
71
74
  end
72
75
  end
73
76
 
@@ -6,6 +6,7 @@ require 'redis_client/cluster/errors'
6
6
  require 'redis_client/cluster/key_slot_converter'
7
7
  require 'redis_client/cluster/node'
8
8
  require 'redis_client/cluster/node_key'
9
+ require 'redis_client/cluster/normalized_cmd_name'
9
10
 
10
11
  class RedisClient
11
12
  class Cluster
@@ -25,7 +26,7 @@ class RedisClient
25
26
  end
26
27
 
27
28
  def send_command(method, command, *args, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
28
- cmd = command.first.to_s.downcase
29
+ cmd = ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_command(command)
29
30
  case cmd
30
31
  when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
31
32
  @node.call_all(method, command, args, &block).first
@@ -65,7 +66,12 @@ class RedisClient
65
66
  # @see https://redis.io/topics/cluster-spec#redirection-and-resharding
66
67
  # Redirection and resharding
67
68
  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
+ if args.empty?
70
+ # prevent memory allocation for variable-length args
71
+ node.send(method, command, &block)
72
+ else
73
+ node.send(method, *args, command, &block)
74
+ end
69
75
  rescue ::RedisClient::CommandError => e
70
76
  raise if retry_count <= 0
71
77
 
@@ -193,7 +199,7 @@ class RedisClient
193
199
  end
194
200
 
195
201
  def send_config_command(method, command, args, &block)
196
- case command[1].to_s.downcase
202
+ case ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_subcommand(command)
197
203
  when 'resetstat', 'rewrite', 'set'
198
204
  @node.call_all(method, command, args, &block).first
199
205
  else assign_node(command).send(method, *args, command, &block)
@@ -201,7 +207,7 @@ class RedisClient
201
207
  end
202
208
 
203
209
  def send_memory_command(method, command, args, &block)
204
- case command[1].to_s.downcase
210
+ case ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_subcommand(command)
205
211
  when 'stats' then @node.call_all(method, command, args, &block)
206
212
  when 'purge' then @node.call_all(method, command, args, &block).first
207
213
  else assign_node(command).send(method, *args, command, &block)
@@ -209,7 +215,7 @@ class RedisClient
209
215
  end
210
216
 
211
217
  def send_client_command(method, command, args, &block)
212
- case command[1].to_s.downcase
218
+ case ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_subcommand(command)
213
219
  when 'list' then @node.call_all(method, command, args, &block).flatten
214
220
  when 'pause', 'reply', 'setname'
215
221
  @node.call_all(method, command, args, &block).first
@@ -217,10 +223,8 @@ class RedisClient
217
223
  end
218
224
  end
219
225
 
220
- def send_cluster_command(method, command, args, &block) # rubocop:disable Metrics/MethodLength
221
- subcommand = command[1].to_s.downcase
222
-
223
- case subcommand
226
+ def send_cluster_command(method, command, args, &block)
227
+ case subcommand = ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_subcommand(command)
224
228
  when 'addslots', 'delslots', 'failover', 'forget', 'meet', 'replicate',
225
229
  'reset', 'set-config-epoch', 'setslot'
226
230
  raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, ['cluster', subcommand]
@@ -234,7 +238,7 @@ class RedisClient
234
238
  end
235
239
 
236
240
  def send_script_command(method, command, args, &block)
237
- case command[1].to_s.downcase
241
+ case ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_subcommand(command)
238
242
  when 'debug', 'kill'
239
243
  @node.call_all(method, command, args, &block).first
240
244
  when 'flush', 'load'
@@ -244,7 +248,7 @@ class RedisClient
244
248
  end
245
249
 
246
250
  def send_pubsub_command(method, command, args, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
247
- case command[1].to_s.downcase
251
+ case ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_subcommand(command)
248
252
  when 'channels' then @node.call_all(method, command, args, &block).flatten.uniq.sort_by(&:to_s)
249
253
  when 'numsub'
250
254
  @node.call_all(method, command, args, &block).reject(&:empty?).map { |e| Hash[*e] }
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.3
4
+ version: 0.3.4
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-18 00:00:00.000000000 Z
11
+ date: 2022-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -42,6 +42,7 @@ files:
42
42
  - lib/redis_client/cluster/node/random_replica.rb
43
43
  - lib/redis_client/cluster/node/replica_mixin.rb
44
44
  - lib/redis_client/cluster/node_key.rb
45
+ - lib/redis_client/cluster/normalized_cmd_name.rb
45
46
  - lib/redis_client/cluster/pipeline.rb
46
47
  - lib/redis_client/cluster/pub_sub.rb
47
48
  - lib/redis_client/cluster/router.rb