Skip to content

Commit

Permalink
Merge 053a5e1 into 0347c85
Browse files Browse the repository at this point in the history
  • Loading branch information
kbaum committed Oct 7, 2019
2 parents 0347c85 + 053a5e1 commit 11c3320
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 55 deletions.
58 changes: 34 additions & 24 deletions lib/coverband/adapters/hash_redis_store.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'securerandom'

module Coverband
module Adapters
class HashRedisStore < Base
Expand Down Expand Up @@ -54,24 +56,27 @@ def save_report(report)
report_time = Time.now.to_i
updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
script_id = hash_incr_script
@redis.pipelined do
keys = report.map do |file, data|
relative_file = @relative_file_converter.convert(file)
file_hash = file_hash(relative_file)
key = key(relative_file, file_hash: file_hash)
script_input = save_report_script_input(
key: key,
file: relative_file,
file_hash: file_hash,
data: data,
report_time: report_time,
updated_time: updated_time
)
@redis.evalsha(script_id, script_input[:keys], script_input[:args])
key
end
@redis.sadd(files_key, keys) if keys.any?
end
keys = []
json = report.map do |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
)
end.to_json
return unless keys.any?

arguments_key = [@redis_namespace, SecureRandom.uuid].compact.join('.')
@redis.set(arguments_key, json)
@redis.evalsha(script_id, [arguments_key])
@redis.sadd(files_key, keys)
end

def coverage(local_type = nil)
Expand Down Expand Up @@ -116,13 +121,18 @@ def coverage_data_from_redis(data_from_redis)
end
end

def save_report_script_input(key:, file:, file_hash:, data:, report_time:, updated_time:)
def script_input(key:, file:, file_hash:, data:, report_time:, updated_time:)
data.each_with_index
.each_with_object(keys: [key], args: [report_time, updated_time, file, file_hash, @ttl, data.length]) do |(coverage, index), hash|
if coverage
hash[:keys] << index
hash[:args] << coverage
end
.each_with_object(
first_updated_at: report_time,
last_updated_at: updated_time,
file: file,
file_hash: file_hash,
ttl: @ttl,
file_length: data.length,
hash_key: key
) do |(coverage, index), hash|
hash[index] = coverage if coverage
end
end

Expand Down
2 changes: 1 addition & 1 deletion lua/install.sh
Expand Up @@ -5,6 +5,6 @@ pip install hererocks
hererocks $LUA_DIR -l5.1 -rlatest
source $LUA_DIR/bin/activate
lua -v
for i in luacov busted redis-lua inspect; do
for i in luacov busted redis-lua inspect lua-cjson; do
luarocks install $i;
done
47 changes: 30 additions & 17 deletions lua/lib/persist-coverage.lua
@@ -1,19 +1,32 @@
local first_updated_at = table.remove(ARGV, 1)
local last_updated_at = table.remove(ARGV, 1)
local file = table.remove(ARGV, 1)
local file_hash = table.remove(ARGV, 1)
local ttl = table.remove(ARGV, 1)
local file_length = table.remove(ARGV, 1)
local hash_key = table.remove(KEYS, 1)
redis.call('HMSET', hash_key, 'last_updated_at', last_updated_at, 'file', file, 'file_hash', file_hash, 'file_length', file_length)
redis.call('HSETNX', hash_key, 'first_updated_at', first_updated_at)
for i, key in ipairs(KEYS) do
if ARGV[i] == '-1' then
redis.call("HSET", hash_key, key, ARGV[i])
else
redis.call("HINCRBY", hash_key, key, ARGV[i])
local hash_values_array = cjson.decode(redis.call('get', (KEYS[1])))
redis.call('DEL', KEYS[1])
for i, hash_values in ipairs(hash_values_array) do
local function remove(key)
local val = hash_values[key]
hash_values[key] = nil
return val
end
local first_updated_at = remove('first_updated_at')
local last_updated_at = remove('last_updated_at')
local file = remove('file')
local file_hash = remove('file_hash')
local ttl = remove('ttl')
local file_length = remove('file_length')
local hash_key = remove('hash_key')
redis.call('HMSET', hash_key, 'file', file, 'file_hash', file_hash, 'file_length', file_length)

if (last_updated_at ~= cjson.null) then
redis.call('HSET', hash_key, 'last_updated_at', last_updated_at)
end
redis.call('HSETNX', hash_key, 'first_updated_at', first_updated_at)
for line, coverage in pairs(hash_values) do
if coverage == '-1' then
redis.call("HSET", hash_key, line, coverage)
else
redis.call("HINCRBY", hash_key, line, coverage)
end
end
if ttl > -1 then
redis.call("EXPIRE", hash_key, ttl)
end
end
if ttl ~= '-1' then
redis.call("EXPIRE", hash_key, ttl)
end
5 changes: 5 additions & 0 deletions lua/test/bootstrap.lua
@@ -0,0 +1,5 @@
inspect = require "inspect"
cjson = require 'cjson'
require './lua/test/redis-call'


3 changes: 1 addition & 2 deletions lua/test/harness.lua
@@ -1,5 +1,4 @@
inspect = require "inspect"
require './lua/test/redis-call'
require './lua/test/bootstrap'


KEYS = {}
Expand Down
8 changes: 8 additions & 0 deletions lua/test/redis-call.lua
Expand Up @@ -36,6 +36,14 @@ redis.call = function(cmd, ...)
end

return result;
end,
hgetall = function()
local new_result = {}
for key, value in pairs(result) do
table.insert(new_result, key)
table.insert(new_result, value)
end
return new_result
end
}

Expand Down
90 changes: 79 additions & 11 deletions lua/test/test-persist-coverage.lua
@@ -1,9 +1,19 @@
local call_redis_script = require "./lua/test/harness";

describe("incr-and-stor", function()
local function hgetall(hash_key)
local flat_map = redis.call('HGETALL', hash_key)
local result = {}
for i = 1, #flat_map, 2 do
result[flat_map[i]] = flat_map[i + 1]
end
return result
end


function clean_redis()
redis.call('DEL', 'coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd')

local function clean_redis()
redis.call('flushdb')
end

before_each(function()
Expand All @@ -14,13 +24,42 @@ describe("incr-and-stor", function()
clean_redis()
end)

it("should add single items", function()
it("Adds data on multiple files", function()
local first_updated_at = "1569453853"
local last_updated_at = first_updated_at
local args = { first_updated_at, last_updated_at, "./dog.rb", "abcd", '-1', 3, 0, 1, 2 }
local keys = {"coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd", 0, 1, 2 }
call_redis_script('persist-coverage.lua', keys , args );
local results = redis.call('HGETALL', "coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd")

local key = 'hash_key'
local json = cjson.encode({
{
hash_key = "coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd",
first_updated_at = first_updated_at,
last_updated_at = last_updated_at,
file = "./dog.rb",
file_hash = 'abcd',
ttl = -1,
file_length = 3,
['0'] = 0,
['1'] = 1,
['2'] = 2
},

{
hash_key = "coverband_hash_3_3.coverband_test.runtime../fish.rb.1234",
first_updated_at = first_updated_at,
last_updated_at = last_updated_at,
file = "./fish.rb",
file_hash = '1234',
ttl = -1,
file_length = 3,
['0'] = 1,
['1'] = 0,
['2'] = 1
}
});
redis.call( 'set', key, json)

call_redis_script('persist-coverage.lua', { key }, {});
local results = hgetall("coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd")
assert.are.same({
["0"] = "0",
["1"] = "1",
Expand All @@ -32,11 +71,39 @@ describe("incr-and-stor", function()
last_updated_at = last_updated_at
}, results)

results = hgetall("coverband_hash_3_3.coverband_test.runtime../fish.rb.1234")
assert.are.same({
["0"] = "1",
["1"] = "0",
["2"] = "1",
file = "./fish.rb",
file_hash = "1234",
file_length = "3",
first_updated_at = first_updated_at ,
last_updated_at = last_updated_at
}, results)



assert.is_false(false, redis.call('exists', key))

last_updated_at = "1569453953"
args = { last_updated_at, last_updated_at, "./dog.rb", "abcd", '-1', 3, 1, 1, 1 }
keys = {"coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd", 0, 1, 2 }
call_redis_script('persist-coverage.lua', keys , args );
results = redis.call('HGETALL', "coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd")
json = cjson.encode({{
hash_key="coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd",
first_updated_at=first_updated_at,
last_updated_at=last_updated_at,
file="./dog.rb",
file_hash='abcd',
ttl=-1,
file_length=3,
['0']= 1,
['1']= 1,
['2']= 1
}})
redis.call( 'set', key, json )

call_redis_script('persist-coverage.lua', { key }, {} );
results = hgetall("coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd")
assert.are.same({
["0"] = "1",
["1"] = "2",
Expand All @@ -48,5 +115,6 @@ describe("incr-and-stor", function()
last_updated_at = last_updated_at
}, results)

assert.is_false(false, redis.call('exists', key))
end)
end)

0 comments on commit 11c3320

Please sign in to comment.