class Coverband::Adapters::HashRedisStore
Constants
- FILE_KEY
- FILE_LENGTH_KEY
- JSON_PAYLOAD_EXPIRATION
- META_DATA_KEYS
- REDIS_STORAGE_FORMAT_VERSION
This key isn't related to the coverband version, but to the interal format used to store data to redis. It is changed only when breaking changes to our redis format are required.
Attributes
redis_namespace[R]
Public Class Methods
new(redis, opts = {})
click to toggle source
Calls superclass method
Coverband::Adapters::Base::new
# File lib/coverband/adapters/hash_redis_store.rb, line 22 def initialize(redis, opts = {}) super() @redis_namespace = opts[:redis_namespace] @save_report_batch_size = opts[:save_report_batch_size] || 100 @format_version = REDIS_STORAGE_FORMAT_VERSION @redis = redis raise "HashRedisStore requires redis >= 2.6.0" unless supported? @ttl = opts[:ttl] @relative_file_converter = opts[:relative_file_converter] || Utils::RelativeFileConverter end
Public Instance Methods
clear!()
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 41 def clear! old_type = type Coverband::TYPES.each do |type| self.type = type file_keys = files_set @redis.del(*file_keys) if file_keys.any? @redis.del(files_key) end self.type = old_type end
clear_file!(file)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 52 def clear_file!(file) file_hash = file_hash(file) relative_path_file = @relative_file_converter.convert(file) Coverband::TYPES.each do |type| @redis.del(key(relative_path_file, type, file_hash: file_hash)) end @redis.srem(files_key, relative_path_file) end
coverage(local_type = nil)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 89 def coverage(local_type = nil) files_set = files_set(local_type) @redis.pipelined { files_set.map do |key| @redis.hgetall(key) end }.each_with_object({}) do |data_from_redis, hash| add_coverage_for_file(data_from_redis, hash) end end
raw_store()
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 100 def raw_store @redis end
save_report(report)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 61 def save_report(report) report_time = Time.now.to_i updated_time = type == Coverband::EAGER_TYPE ? nil : report_time keys = [] report.each_slice(@save_report_batch_size) do |slice| files_data = slice.map { |(file, data)| relative_file = @relative_file_converter.convert(file) file_hash = file_hash(relative_file) key = key(relative_file, file_hash: file_hash) keys << key script_input( key: key, file: relative_file, file_hash: file_hash, data: data, report_time: report_time, updated_time: updated_time ) } next unless files_data.any? arguments_key = [@redis_namespace, SecureRandom.uuid].compact.join(".") @redis.set(arguments_key, {ttl: @ttl, files_data: files_data}.to_json, ex: JSON_PAYLOAD_EXPIRATION) @redis.evalsha(hash_incr_script, [arguments_key]) end @redis.sadd(files_key, keys) if keys.any? end
size()
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 104 def size "not available" end
size_in_mib()
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 108 def size_in_mib "not available" end
supported?()
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 34 def supported? Gem::Version.new(@redis.info["redis_version"]) >= Gem::Version.new("2.6.0") rescue Redis::CannotConnectError => error Coverband.configuration.logger.info "Redis is not available (#{error}), Coverband not configured" Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore" end
Private Instance Methods
add_coverage_for_file(data_from_redis, hash)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 114 def add_coverage_for_file(data_from_redis, hash) return if data_from_redis.empty? file = data_from_redis[FILE_KEY] return unless file_hash(file) == data_from_redis[FILE_HASH] data = coverage_data_from_redis(data_from_redis) hash[file] = data_from_redis.select { |meta_data_key, _value| META_DATA_KEYS.include?(meta_data_key) }.merge!("data" => data) hash[file][LAST_UPDATED_KEY] = hash[file][LAST_UPDATED_KEY].blank? ? nil : hash[file][LAST_UPDATED_KEY].to_i hash[file].merge!(LAST_UPDATED_KEY => hash[file][LAST_UPDATED_KEY], FIRST_UPDATED_KEY => hash[file][FIRST_UPDATED_KEY].to_i) end
coverage_data_from_redis(data_from_redis)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 126 def coverage_data_from_redis(data_from_redis) max = data_from_redis[FILE_LENGTH_KEY].to_i - 1 Array.new(max + 1) do |index| line_coverage = data_from_redis[index.to_s] line_coverage.nil? ? nil : line_coverage.to_i end end
files_key(local_type = nil)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 179 def files_key(local_type = nil) "#{key_prefix(local_type)}.files" end
files_set(local_type = nil)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 175 def files_set(local_type = nil) @redis.smembers(files_key(local_type)) end
hash_incr_script()
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 153 def hash_incr_script @hash_incr_script ||= @redis.script(:load, lua_script_content) end
key(file, local_type = nil, file_hash:)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 183 def key(file, local_type = nil, file_hash:) [key_prefix(local_type), file, file_hash].join(".") end
key_prefix(local_type = nil)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 187 def key_prefix(local_type = nil) local_type ||= type [@format_version, @redis_namespace, local_type].compact.join(".") end
lua_script_content()
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 157 def lua_script_content File.read(File.join( File.dirname(__FILE__), "../../../lua/lib/persist-coverage.lua" )) end
relative_paths(files)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 171 def relative_paths(files) files&.map! { |file| full_path_to_relative(file) } end
script_input(key:, file:, file_hash:, data:, report_time:, updated_time:)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 134 def script_input(key:, file:, file_hash:, data:, report_time:, updated_time:) coverage_data = data.each_with_index.each_with_object({}) { |(coverage, index), hash| hash[index] = coverage if coverage } meta = { first_updated_at: report_time, file: file, file_hash: file_hash, file_length: data.length, hash_key: key } meta[:last_updated_at] = updated_time if updated_time { hash_key: key, meta: meta, coverage: coverage_data } end
values_from_redis(local_type, files)
click to toggle source
# File lib/coverband/adapters/hash_redis_store.rb, line 163 def values_from_redis(local_type, files) return files if files.empty? @redis.mget(*files.map { |file| key(file, local_type) }).map do |value| value.nil? ? {} : JSON.parse(value) end end