Class: Gitlab::Diff::HighlightCache

Inherits:
Object
  • Object
show all
Includes:
Utils::Gzip, Utils::StrongMemoize
Defined in:
lib/gitlab/diff/highlight_cache.rb

Constant Summary collapse

EXPIRATION =
1.hour
VERSION =
2

Instance Method Summary collapse

Methods included from Utils::Gzip

#gzip_compress, #gzip_decompress

Constructor Details

#initialize(diff_collection) ⇒ HighlightCache

Returns a new instance of HighlightCache.



15
16
17
# File 'lib/gitlab/diff/highlight_cache.rb', line 15

def initialize(diff_collection)
  @diff_collection = diff_collection
end

Instance Method Details

#clearObject



64
65
66
67
68
# File 'lib/gitlab/diff/highlight_cache.rb', line 64

def clear
  with_redis do |redis|
    redis.del(key)
  end
end

#decorate(diff_file) ⇒ Object

  • Reads from cache

  • Assigns DiffFile#highlighted_diff_lines for cached files



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/gitlab/diff/highlight_cache.rb', line 22

def decorate(diff_file)
  content = read_file(diff_file)

  return [] unless content

  # TODO: We could add some kind of flag to #initialize that would allow
  #   us to force re-caching
  #   https://gitlab.com/gitlab-org/gitlab/-/issues/263508
  #
  if content.empty? && recache_due_to_size?(diff_file)
    # If the file is missing from the cache and there's reason to believe
    #   it is uncached due to a size issue around changing the values for
    #   max patch size, manually populate the hash and then set the value.
    #
    new_cache_content = {}
    new_cache_content[diff_file.file_path] = diff_file.highlighted_diff_lines.map(&:to_hash)

    write_to_redis_hash(new_cache_content)

    set_highlighted_diff_lines(diff_file, read_file(diff_file))
  else
    set_highlighted_diff_lines(diff_file, content)
  end
end

#keyObject



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/gitlab/diff/highlight_cache.rb', line 70

def key
  strong_memoize(:redis_key) do
    options = [
      diff_options,
      Feature.enabled?(:diff_line_syntax_highlighting, diffable.project)
    ]
    options_for_key = OpenSSL::Digest::SHA256.hexdigest(options.join)

    ['highlighted-diff-files', diffable.cache_key, VERSION, options_for_key].join(":")
  end
end

#write_if_emptyObject

For every file that isn’t already contained in the redis hash, store the

result of #highlighted_diff_lines, then submit the uncached content
to #write_to_redis_hash to submit a single write. This avoids excessive
IO generated by N+1's (1 writing for each highlighted line or file).


52
53
54
55
56
57
58
59
60
61
62
# File 'lib/gitlab/diff/highlight_cache.rb', line 52

def write_if_empty
  return if cacheable_files.empty?

  new_cache_content = {}

  cacheable_files.each do |diff_file|
    new_cache_content[diff_file.file_path] = diff_file.highlighted_diff_lines.map(&:to_hash)
  end

  write_to_redis_hash(new_cache_content)
end