Class: Banzai::Filter::References::ReferenceCache

Inherits:
Object
  • Object
show all
Includes:
RequestStoreReferenceCache, Gitlab::Utils::StrongMemoize
Defined in:
lib/banzai/filter/references/reference_cache.rb

Instance Method Summary collapse

Methods included from RequestStoreReferenceCache

#cached_call, #get_or_set_cache

Methods included from Gitlab::Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

Constructor Details

#initialize(filter, context, result) ⇒ ReferenceCache

Returns a new instance of ReferenceCache.


10
11
12
13
14
# File 'lib/banzai/filter/references/reference_cache.rb', line 10

def initialize(filter, context, result)
  @filter = filter
  @context = context
  @result = result || {}
end

Instance Method Details

#cache_loaded?Boolean

Returns:

  • (Boolean)

164
165
166
# File 'lib/banzai/filter/references/reference_cache.rb', line 164

def cache_loaded?
  !!@cache_loaded
end

#current_parent_pathObject


139
140
141
142
143
# File 'lib/banzai/filter/references/reference_cache.rb', line 139

def current_parent_path
  strong_memoize(:current_parent_path) do
    parent&.full_path
  end
end

#current_project_namespace_pathObject


145
146
147
148
149
# File 'lib/banzai/filter/references/reference_cache.rb', line 145

def current_project_namespace_path
  strong_memoize(:current_project_namespace_path) do
    project&.namespace&.full_path
  end
end

#find_for_paths(paths) ⇒ Object

Returns projects for the given paths.


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/banzai/filter/references/reference_cache.rb', line 112

def find_for_paths(paths)
  if Gitlab::SafeRequestStore.active?
    cache = refs_cache
    to_query = paths - cache.keys

    unless to_query.empty?
      records = objects_for_paths(to_query)

      found = []
      records.each do |record|
        ref = record.full_path
        get_or_set_cache(cache, ref) { record }
        found << ref
      end

      not_found = to_query - found
      not_found.each do |ref|
        get_or_set_cache(cache, ref) { nil }
      end
    end

    cache.slice(*paths).values.compact
  else
    objects_for_paths(paths)
  end
end

#full_group_path(group_ref) ⇒ Object


158
159
160
161
162
# File 'lib/banzai/filter/references/reference_cache.rb', line 158

def full_group_path(group_ref)
  return current_parent_path unless group_ref

  group_ref
end

#full_project_path(namespace, project_ref) ⇒ Object


151
152
153
154
155
156
# File 'lib/banzai/filter/references/reference_cache.rb', line 151

def full_project_path(namespace, project_ref)
  return current_parent_path unless project_ref

  namespace_ref = namespace || current_project_namespace_path
  "#{namespace_ref}/#{project_ref}"
end

#load_parent_per_referenceObject

Returns a Hash containing referenced projects grouped per their full path.


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/banzai/filter/references/reference_cache.rb', line 53

def load_parent_per_reference
  @per_reference ||= {}

  @per_reference[parent_type] ||= begin
    refs = references_per_parent.keys
    parent_ref = {}

    # if we already have a parent, no need to query it again
    refs.each do |ref|
      next unless ref

      if context[:project]&.full_path == ref
        parent_ref[ref] = context[:project]
      elsif context[:group]&.full_path == ref
        parent_ref[ref] = context[:group]
      end

      refs -= [ref] if parent_ref[ref]
    end

    find_for_paths(refs).index_by(&:full_path).merge(parent_ref)
  end
end

#load_records_per_parentObject


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/banzai/filter/references/reference_cache.rb', line 81

def load_records_per_parent
  @_records_per_project ||= {}

  @_records_per_project[filter.object_class.to_s.underscore] ||= begin
    hash = Hash.new { |h, k| h[k] = {} }

    parent_per_reference.each do |path, parent|
      record_ids = references_per_parent[path]

      filter.parent_records(parent, record_ids).each do |record|
        hash[parent][filter.record_identifier(record)] = record
      end
    end

    hash
  end
end

#load_reference_cache(nodes) ⇒ Object


16
17
18
19
20
21
22
# File 'lib/banzai/filter/references/reference_cache.rb', line 16

def load_reference_cache(nodes)
  load_references_per_parent(nodes)
  load_parent_per_reference
  load_records_per_parent

  @cache_loaded = true
end

#load_references_per_parent(nodes) ⇒ Object

Loads all object references (e.g. issue IDs) per project/group they belong to.


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/banzai/filter/references/reference_cache.rb', line 26

def load_references_per_parent(nodes)
  @references_per_parent ||= {}

  @references_per_parent[parent_type] ||= begin
    refs = Hash.new { |hash, key| hash[key] = Set.new }

    prepare_doc_for_scan.to_enum(:scan, regex).each do
      parent_path = if parent_type == :project
                      full_project_path($~[:namespace], $~[:project])
                    else
                      full_group_path($~[:group])
                    end

      ident = filter.identifier($~)
      refs[parent_path] << ident if ident
    end

    refs
  end
end

#objects_for_paths(paths) ⇒ Object


103
104
105
106
107
108
109
# File 'lib/banzai/filter/references/reference_cache.rb', line 103

def objects_for_paths(paths)
  klass = parent_type.to_s.camelize.constantize
  result = klass.where_full_path_in(paths)
  return result if parent_type == :group

  result.includes(namespace: :route) if parent_type == :project
end

#parent_per_referenceObject


77
78
79
# File 'lib/banzai/filter/references/reference_cache.rb', line 77

def parent_per_reference
  @per_reference[parent_type]
end

#records_per_parentObject


99
100
101
# File 'lib/banzai/filter/references/reference_cache.rb', line 99

def records_per_parent
  @_records_per_project[filter.object_class.to_s.underscore]
end

#references_per_parentObject


47
48
49
# File 'lib/banzai/filter/references/reference_cache.rb', line 47

def references_per_parent
  @references_per_parent[parent_type]
end