Module: JetstreamBridge::SubjectMatcher

Defined in:
lib/jetstream_bridge/topology/subject_matcher.rb

Overview

Subject matching helpers.

Class Method Summary collapse

Class Method Details

.covered?(patterns, subject) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
# File 'lib/jetstream_bridge/topology/subject_matcher.rb', line 8

def covered?(patterns, subject)
  Array(patterns).any? { |pat| match?(pat.to_s, subject.to_s) }
end

.match?(pattern, subject) ⇒ Boolean

Proper NATS semantics:

  • ‘*’ matches exactly one token

  • ‘>’ matches the rest (zero or more tokens)

Returns:

  • (Boolean)


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/jetstream_bridge/topology/subject_matcher.rb', line 15

def match?(pattern, subject)
  p = pattern.split('.')
  s = subject.split('.')

  i = 0
  while i < p.length && i < s.length
    token = p[i]
    case token
    when '>'
      return true # tail wildcard absorbs the rest
    when '*'
      # matches this token; continue
    else
      return false unless token == s[i]
    end
    i += 1
  end

  # Exact match
  return true if i == p.length && i == s.length

  # If pattern has remaining '>' it can absorb remainder
  p[i] == '>' || p[i..]&.include?('>')
end

.overlap?(sub_a, sub_b) ⇒ Boolean

Do two wildcard patterns admit at least one same subject?

Returns:

  • (Boolean)


41
42
43
# File 'lib/jetstream_bridge/topology/subject_matcher.rb', line 41

def overlap?(sub_a, sub_b)
  overlap_parts?(sub_a.split('.'), sub_b.split('.'))
end

.overlap_parts?(a_parts, b_parts) ⇒ Boolean

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/jetstream_bridge/topology/subject_matcher.rb', line 45

def overlap_parts?(a_parts, b_parts)
  ai = 0
  bi = 0
  while ai < a_parts.length && bi < b_parts.length
    at = a_parts[ai]
    bt = b_parts[bi]
    return true if tail?(at, bt)
    return false unless token_match?(at, bt)

    ai += 1
    bi += 1
  end

  tail_overlap?(a_parts[ai..], b_parts[bi..])
end

.tail?(a_token, b_token) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/jetstream_bridge/topology/subject_matcher.rb', line 61

def tail?(a_token, b_token)
  a_token == '>' || b_token == '>'
end

.tail_overlap?(a_tail, b_tail) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
75
# File 'lib/jetstream_bridge/topology/subject_matcher.rb', line 69

def tail_overlap?(a_tail, b_tail)
  a_tail ||= []
  b_tail ||= []
  return true if a_tail.include?('>') || b_tail.include?('>')

  a_tail.empty? && b_tail.empty?
end

.token_match?(a_token, b_token) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/jetstream_bridge/topology/subject_matcher.rb', line 65

def token_match?(a_token, b_token)
  a_token == b_token || a_token == '*' || b_token == '*'
end