diff options
Diffstat (limited to 'lib/gitlab/diff/highlight_cache.rb')
-rw-r--r-- | lib/gitlab/diff/highlight_cache.rb | 41 |
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 |