summaryrefslogtreecommitdiff
path: root/lib/gitlab/diff/highlight_cache.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/diff/highlight_cache.rb')
-rw-r--r--lib/gitlab/diff/highlight_cache.rb41
1 files changed, 39 insertions, 2 deletions
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index 055eae2c0fd..01ec9798fe4 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -94,7 +94,11 @@ module Gitlab
Gitlab::Redis::Cache.with do |redis|
redis.pipelined do
hash.each do |diff_file_id, highlighted_diff_lines_hash|
- redis.hset(key, diff_file_id, highlighted_diff_lines_hash.to_json)
+ redis.hset(
+ key,
+ diff_file_id,
+ compose_data(highlighted_diff_lines_hash.to_json)
+ )
end
# HSETs have to have their expiration date manually updated
@@ -152,12 +156,45 @@ module Gitlab
end
results.map! do |result|
- JSON.parse(result, symbolize_names: true) unless result.nil?
+ JSON.parse(extract_data(result), symbolize_names: true) unless result.nil?
end
file_paths.zip(results).to_h
end
+ def compose_data(json_data)
+ if ::Feature.enabled?(:gzip_diff_cache, default_enabled: true)
+ # #compress returns ASCII-8BIT, so we need to force the encoding to
+ # UTF-8 before caching it in redis, else we risk encoding mismatch
+ # errors.
+ #
+ ActiveSupport::Gzip.compress(json_data).force_encoding("UTF-8")
+ else
+ json_data
+ end
+ rescue Zlib::GzipFile::Error
+ json_data
+ end
+
+ def extract_data(data)
+ # Since when we deploy this code, we'll be dealing with an already
+ # populated cache full of data that isn't gzipped, we want to also
+ # check to see if the data is gzipped before we attempt to #decompress
+ # it, thus we check the first 2 bytes for "\x1F\x8B" to confirm it is
+ # a gzipped string. While a non-gzipped string will raise a
+ # Zlib::GzipFile::Error, which we're rescuing, we don't want to count
+ # on rescue for control flow. This check can be removed in the release
+ # after this change is released.
+ #
+ if ::Feature.enabled?(:gzip_diff_cache, default_enabled: true) && data[0..1] == "\x1F\x8B"
+ ActiveSupport::Gzip.decompress(data)
+ else
+ data
+ end
+ rescue Zlib::GzipFile::Error
+ data
+ end
+
def cacheable?(diff_file)
diffable.present? && diff_file.text? && diff_file.diffable?
end