Skip to content

Commit 7127f3b

Browse files
authored
Merge pull request #894 from rahul342/master
Extend SlotLoader to work with multiple slot ranges
2 parents 41395e9 + 5849cb2 commit 7127f3b

File tree

3 files changed

+69
-9
lines changed

3 files changed

+69
-9
lines changed

lib/redis/cluster/slot.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ def slave?(node_key)
5050
@node_flags[node_key] == ROLE_SLAVE
5151
end
5252

53+
# available_slots is mapping of node_key to list of slot ranges
5354
def build_slot_node_key_map(available_slots)
54-
available_slots.each_with_object({}) do |(node_key, slots), acc|
55-
slots.each { |slot| assign_node_key(acc, slot, node_key) }
55+
available_slots.each_with_object({}) do |(node_key, slots_arr), acc|
56+
slots_arr.each do |slots|
57+
slots.each { |slot| assign_node_key(acc, slot, node_key) }
58+
end
5659
end
5760
end
5861

lib/redis/cluster/slot_loader.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def load(nodes)
1313
info = {}
1414

1515
nodes.each do |node|
16-
info = Hash[*fetch_slot_info(node)]
16+
info = fetch_slot_info(node)
1717
info.empty? ? next : break
1818
end
1919

@@ -23,9 +23,11 @@ def load(nodes)
2323
end
2424

2525
def fetch_slot_info(node)
26+
hash_with_default_arr = Hash.new { |h, k| h[k] = [] }
2627
node.call(%i[cluster slots])
27-
.map { |arr| parse_slot_info(arr, default_ip: node.host) }
28-
.flatten
28+
.flat_map { |arr| parse_slot_info(arr, default_ip: node.host) }
29+
.each_with_object(hash_with_default_arr) { |arr, h| h[arr[0]] << arr[1] }
30+
2931
rescue CannotConnectError, ConnectionError, CommandError
3032
{} # can retry on another node
3133
end
@@ -34,7 +36,6 @@ def parse_slot_info(arr, default_ip:)
3436
first_slot, last_slot = arr[0..1]
3537
slot_range = (first_slot..last_slot).freeze
3638
arr[2..-1].map { |addr| [stringify_node_key(addr, default_ip), slot_range] }
37-
.flatten
3839
end
3940

4041
def stringify_node_key(arr, default_ip)

test/cluster_client_slots_test.rb

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class TestClusterClientSlots < Minitest::Test
77
include Helper::Cluster
88

99
def test_slot_class
10-
slot = Redis::Cluster::Slot.new('127.0.0.1:7000' => 1..10)
10+
slot = Redis::Cluster::Slot.new('127.0.0.1:7000' => [1..10])
1111

1212
assert_equal false, slot.exists?(0)
1313
assert_equal true, slot.exists?(1)
@@ -26,15 +26,67 @@ def test_slot_class
2626
assert_nil slot.put(1, '127.0.0.1:7001')
2727
end
2828

29+
def test_slot_class_with_multiple_slot_ranges
30+
slot = Redis::Cluster::Slot.new('127.0.0.1:7000' => [1..10, 30..40])
31+
32+
assert_equal false, slot.exists?(0)
33+
assert_equal true, slot.exists?(1)
34+
assert_equal true, slot.exists?(10)
35+
assert_equal false, slot.exists?(11)
36+
assert_equal true, slot.exists?(30)
37+
assert_equal true, slot.exists?(40)
38+
assert_equal false, slot.exists?(41)
39+
40+
assert_nil slot.find_node_key_of_master(0)
41+
assert_nil slot.find_node_key_of_slave(0)
42+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
43+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(1)
44+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
45+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(10)
46+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(30)
47+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(40)
48+
assert_nil slot.find_node_key_of_master(11)
49+
assert_nil slot.find_node_key_of_slave(11)
50+
assert_nil slot.find_node_key_of_master(41)
51+
assert_nil slot.find_node_key_of_slave(41)
52+
53+
assert_nil slot.put(1, '127.0.0.1:7001')
54+
assert_nil slot.put(30, '127.0.0.1:7001')
55+
end
56+
2957
def test_slot_class_with_node_flags_and_replicas
30-
slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => 1..10, '127.0.0.1:7001' => 1..10 },
58+
slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => [1..10], '127.0.0.1:7001' => [1..10] },
59+
{ '127.0.0.1:7000' => 'master', '127.0.0.1:7001' => 'slave' },
60+
true)
61+
62+
assert_equal false, slot.exists?(0)
63+
assert_equal true, slot.exists?(1)
64+
assert_equal true, slot.exists?(10)
65+
assert_equal false, slot.exists?(11)
66+
67+
assert_nil slot.find_node_key_of_master(0)
68+
assert_nil slot.find_node_key_of_slave(0)
69+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
70+
assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(1)
71+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
72+
assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(10)
73+
assert_nil slot.find_node_key_of_master(11)
74+
assert_nil slot.find_node_key_of_slave(11)
75+
76+
assert_nil slot.put(1, '127.0.0.1:7002')
77+
end
78+
79+
def test_slot_class_with_node_flags_replicas_and_slot_range
80+
slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => [1..10, 30..40], '127.0.0.1:7001' => [1..10, 30..40] },
3181
{ '127.0.0.1:7000' => 'master', '127.0.0.1:7001' => 'slave' },
3282
true)
3383

3484
assert_equal false, slot.exists?(0)
3585
assert_equal true, slot.exists?(1)
3686
assert_equal true, slot.exists?(10)
3787
assert_equal false, slot.exists?(11)
88+
assert_equal true, slot.exists?(30)
89+
assert_equal false, slot.exists?(41)
3890

3991
assert_nil slot.find_node_key_of_master(0)
4092
assert_nil slot.find_node_key_of_slave(0)
@@ -44,12 +96,16 @@ def test_slot_class_with_node_flags_and_replicas
4496
assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(10)
4597
assert_nil slot.find_node_key_of_master(11)
4698
assert_nil slot.find_node_key_of_slave(11)
99+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(30)
100+
assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(30)
101+
assert_nil slot.find_node_key_of_master(41)
102+
assert_nil slot.find_node_key_of_slave(41)
47103

48104
assert_nil slot.put(1, '127.0.0.1:7002')
49105
end
50106

51107
def test_slot_class_with_node_flags_and_without_replicas
52-
slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => 1..10, '127.0.0.1:7001' => 1..10 },
108+
slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => [1..10], '127.0.0.1:7001' => [1..10] },
53109
{ '127.0.0.1:7000' => 'master', '127.0.0.1:7001' => 'slave' },
54110
false)
55111

0 commit comments

Comments
 (0)