@@ -18,10 +18,12 @@ class Node
1818 MAX_STARTUP_SAMPLE = 37
1919 MAX_THREADS = Integer ( ENV . fetch ( 'REDIS_CLIENT_MAX_THREADS' , 5 ) )
2020 IGNORE_GENERIC_CONFIG_KEYS = %i[ url host port path ] . freeze
21+ SLOT_OPTIMIZATION_STRING = '0' * SLOT_SIZE
2122
2223 ReloadNeeded = Class . new ( ::RedisClient ::Error )
24+
2325 Info = Struct . new (
24- 'RedisNode ' ,
26+ 'RedisClusterNode ' ,
2527 :id , :node_key , :role , :primary_id , :ping_sent ,
2628 :pong_recv , :config_epoch , :link_state , :slots ,
2729 keyword_init : true
@@ -35,23 +37,27 @@ def replica?
3537 end
3638 end
3739
38- SLOT_OPTIMIZATION_MAX_SHARD_SIZE = 256
39- SLOT_OPTIMIZATION_STRING = '0' * SLOT_SIZE
40- Slot = Struct . new ( 'RedisSlot' , :slots , :primary_node_keys , keyword_init : true ) do
41- def []( slot )
42- primary_node_keys [ slots . getbyte ( slot ) ]
40+ Slot = Struct . new ( 'StringArray' , :string , :elements , keyword_init : true ) do
41+ def []( index )
42+ raise IndexError if index < 0
43+ return if index >= string . bytesize
44+
45+ elements [ string . getbyte ( index ) ]
4346 end
4447
45- def []=( slot , primary_node_key )
46- index = primary_node_keys . find_index ( primary_node_key )
47- if index . nil?
48- raise ( ::RedisClient ::Cluster ::Node ::ReloadNeeded , primary_node_key ) if primary_node_keys . size >= SLOT_OPTIMIZATION_MAX_SHARD_SIZE
48+ def []=( index , element )
49+ raise IndexError if index < 0
50+ return if index >= string . bytesize
51+
52+ pos = elements . find_index ( element ) # O(N)
53+ if pos . nil?
54+ raise ( RangeError , 'full of elements' ) if elements . size >= 256
4955
50- index = primary_node_keys . size
51- primary_node_keys << primary_node_key
56+ pos = elements . size
57+ elements << element
5258 end
5359
54- slots . setbyte ( slot , index )
60+ string . setbyte ( index , pos )
5561 end
5662 end
5763
@@ -229,7 +235,12 @@ def any_replica_node_key(seed: nil)
229235 def update_slot ( slot , node_key )
230236 return if @mutex . locked?
231237
232- @mutex . synchronize { @slots [ slot ] = node_key }
238+ @mutex . synchronize do
239+ @slots [ slot ] = node_key
240+ rescue RangeError
241+ @slots = Array . new ( SLOT_SIZE ) { |i | @slots [ i ] }
242+ @slots [ slot ] = node_key
243+ end
233244 end
234245
235246 private
@@ -256,11 +267,11 @@ def build_slot_node_mappings(node_info_list)
256267 end
257268
258269 def make_array_for_slot_node_mappings ( node_info_list )
259- return Array . new ( SLOT_SIZE ) if node_info_list . count ( &:primary? ) > SLOT_OPTIMIZATION_MAX_SHARD_SIZE
270+ return Array . new ( SLOT_SIZE ) if node_info_list . count ( &:primary? ) > 256
260271
261272 ::RedisClient ::Cluster ::Node ::Slot . new (
262- slots : String . new ( SLOT_OPTIMIZATION_STRING , encoding : Encoding ::BINARY , capacity : SLOT_SIZE ) ,
263- primary_node_keys : node_info_list . select ( &:primary? ) . map ( &:node_key )
273+ string : String . new ( SLOT_OPTIMIZATION_STRING , encoding : Encoding ::BINARY , capacity : SLOT_SIZE ) ,
274+ elements : node_info_list . select ( &:primary? ) . map ( &:node_key )
264275 )
265276 end
266277
0 commit comments