-
Notifications
You must be signed in to change notification settings - Fork 1k
/
slot.rb
86 lines (68 loc) · 2.12 KB
/
slot.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# frozen_string_literal: true
class Redis
class Cluster
# Keep slot and node key map for Redis Cluster Client
class Slot
ROLE_SLAVE = 'slave'
def initialize(available_slots, node_flags = {}, with_replica = false)
@with_replica = with_replica
@node_flags = node_flags
@map = build_slot_node_key_map(available_slots)
end
def exists?(slot)
@map.key?(slot)
end
def find_node_key_of_master(slot)
return nil unless exists?(slot)
@map[slot][:master]
end
def find_node_key_of_slave(slot)
return nil unless exists?(slot)
return find_node_key_of_master(slot) if replica_disabled?
@map[slot][:slaves].sample
end
def put(slot, node_key)
# Since we're sharing a hash for build_slot_node_key_map, duplicate it
# if it already exists instead of preserving as-is.
@map[slot] = @map[slot] ? @map[slot].dup : { master: nil, slaves: [] }
if master?(node_key)
@map[slot][:master] = node_key
elsif !@map[slot][:slaves].include?(node_key)
@map[slot][:slaves] << node_key
end
nil
end
private
def replica_disabled?
!@with_replica
end
def master?(node_key)
!slave?(node_key)
end
def slave?(node_key)
@node_flags[node_key] == ROLE_SLAVE
end
# available_slots is mapping of node_key to list of slot ranges
def build_slot_node_key_map(available_slots)
by_ranges = {}
available_slots.each do |node_key, slots_arr|
by_ranges[slots_arr] ||= { master: nil, slaves: [] }
if master?(node_key)
by_ranges[slots_arr][:master] = node_key
elsif !by_ranges[slots_arr][:slaves].include?(node_key)
by_ranges[slots_arr][:slaves] << node_key
end
end
by_slot = {}
by_ranges.each do |slots_arr, nodes|
slots_arr.each do |slots|
slots.each do |slot|
by_slot[slot] = nodes
end
end
end
by_slot
end
end
end
end