Module: Gitlab::Instrumentation::RedisClusterRouter

Defined in:
lib/gitlab/instrumentation/redis_cluster_router.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.compact_array(arr) ⇒ Object

compact_array converts an array of integers into a range string e.g. [0, 1, 2, 4, 5, 6] to “0-2,4-6”



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/gitlab/instrumentation/redis_cluster_router.rb', line 57

def compact_array(arr)
  return "" if arr.empty?

  range = ""
  prev = nil
  arr.each do |i|
    if prev.nil?
      range += i.to_s
    elsif prev + 1 < i
      range += "-#{prev},#{i}"
    end

    prev = i
  end
  range += "-#{prev}"

  range
end

.format_slotmap(slots) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/gitlab/instrumentation/redis_cluster_router.rb', line 40

def format_slotmap(slots)
  return {} unless slots

  slotmap = {}
  (0..16383).each do |c|
    node_key = slots[c]
    next unless node_key

    slotmap[node_key] ||= []
    slotmap[node_key] << c
  end

  slotmap.transform_values { |v| compact_array(v) }
end

Instance Method Details

#send_command(method, command, *args, &block) ⇒ Object

Patch the send_command method in RedisClient::Cluster::Router See github.com/redis-rb/redis-cluster-client/blob/v0.8.2/lib/redis_client/cluster/router.rb#L34

When a Redis Cluster is in a fail state, we might not have metrics on the server-side. This allows the application to dump its local topology state to get the client-side perspective of any cluster failure.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/gitlab/instrumentation/redis_cluster_router.rb', line 12

def send_command(method, command, *args, &block)
  super
rescue ::RedisClient::Cluster::NodeMightBeDown => e
  # rubocop:disable Gitlab/ModuleWithInstanceVariables -- this class is used to monkeypatch RedisClient::Cluster::Router
  slots_map = Gitlab::Instrumentation::RedisClusterRouter.format_slotmap(@node.instance_variable_get(:@slots))
  Gitlab::ErrorTracking.log_exception(
    e,
    node_keys: @node.node_keys,
    slots_map: slots_map
  )

  inst = instrumentation_class(@config)
  inst.instance_count_exception(e) if inst
  # rubocop:enable Gitlab/ModuleWithInstanceVariables

  raise e
end