Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up lua script #332

Merged
merged 3 commits into from
Oct 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 22 additions & 17 deletions lib/coverband/adapters/hash_redis_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class HashRedisStore < Base
###
REDIS_STORAGE_FORMAT_VERSION = 'coverband_hash_3_3'

JSON_PAYLOAD_EXPIRATION = 5 * 60

attr_reader :redis_namespace

def initialize(redis, opts = {})
Expand All @@ -24,7 +26,7 @@ def initialize(redis, opts = {})
@redis = redis
raise 'HashRedisStore requires redis >= 2.6.0' unless supported?

@ttl = opts[:ttl] || -1
@ttl = opts[:ttl]
@relative_file_converter = opts[:relative_file_converter] || Utils::RelativeFileConverter
end

Expand Down Expand Up @@ -55,27 +57,26 @@ def clear_file!(file)
def save_report(report)
report_time = Time.now.to_i
updated_time = type == Coverband::EAGER_TYPE ? nil : report_time
script_id = hash_incr_script
keys = []
json = report.map do |file, data|
files_data = 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,
file_hash: file_hash(relative_file),
data: data,
report_time: report_time,
updated_time: updated_time
)
end.to_json
end
return unless keys.any?

arguments_key = [@redis_namespace, SecureRandom.uuid].compact.join('.')
@redis.set(arguments_key, json)
@redis.evalsha(script_id, [arguments_key])
@redis.set(arguments_key, { ttl: @ttl, files_data: files_data }.to_json, ex: JSON_PAYLOAD_EXPIRATION)
@redis.evalsha(hash_incr_script, [arguments_key])
@redis.sadd(files_key, keys)
end

Expand Down Expand Up @@ -122,18 +123,22 @@ def coverage_data_from_redis(data_from_redis)
end

def script_input(key:, file:, file_hash:, data:, report_time:, updated_time:)
data.each_with_index
.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|
coverage_data = data.each_with_index.each_with_object({}) do |(coverage, index), hash|
hash[index] = coverage if coverage
end
meta = {
first_updated_at: report_time,
file: file,
file_hash: file_hash,
file_length: data.length,
hash_key: key
}
meta.merge!(last_updated_at: updated_time) if updated_time
{
hash_key: key,
meta: meta,
coverage: coverage_data
}
end

def hash_incr_script
Expand Down
46 changes: 21 additions & 25 deletions lua/lib/persist-coverage.lua
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
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
local hmset = function (key, dict)
if next(dict) == nil then return nil end
local bulk = {}
for k, v in pairs(dict) do
table.insert(bulk, k)
table.insert(bulk, v)
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)
return redis.call('HMSET', key, unpack(bulk))
end
local payload = cjson.decode(redis.call('get', (KEYS[1])))
local ttl = payload.ttl
local files_data = payload.files_data
redis.call('DEL', KEYS[1])
for _, file_data in ipairs(files_data) do

if (last_updated_at ~= cjson.null) then
redis.call('HSET', hash_key, 'last_updated_at', last_updated_at)
end
local hash_key = file_data.hash_key
local first_updated_at = file_data.meta.first_updated_at
file_data.meta.first_updated_at = nil

hmset(hash_key, file_data.meta)
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
for line, coverage in pairs(file_data.coverage) do
redis.call("HINCRBY", hash_key, line, coverage)
end
if ttl > -1 then
if ttl and ttl ~= cjson.null then
redis.call("EXPIRE", hash_key, ttl)
end
end
94 changes: 53 additions & 41 deletions lua/test/test-persist-coverage.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local call_redis_script = require "./lua/test/harness";

describe("incr-and-stor", function()
describe("persist-coverage", function()
local function hgetall(hash_key)
local flat_map = redis.call('HGETALL', hash_key)
local result = {}
Expand All @@ -10,8 +10,6 @@ describe("incr-and-stor", function()
return result
end



local function clean_redis()
redis.call('flushdb')
end
Expand All @@ -30,30 +28,38 @@ describe("incr-and-stor", function()

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
ttl = nil,
files_data = {
{
hash_key = "coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd",
meta = {
first_updated_at = first_updated_at,
last_updated_at = last_updated_at,
file = "./dog.rb",
file_hash = 'abcd',
file_length = 3
},
coverage = {
['0'] = 0,
['1'] = 1,
['2'] = 2
}
},
{
hash_key = "coverband_hash_3_3.coverband_test.runtime../fish.rb.1234",
meta = {
first_updated_at = first_updated_at,
last_updated_at = last_updated_at,
file = "./fish.rb",
file_hash = '1234',
file_length = 3
},
coverage = {
['0'] = 1,
['1'] = 0,
['2'] = 1
}
}
}
});
redis.call( 'set', key, json)
Expand Down Expand Up @@ -83,23 +89,29 @@ describe("incr-and-stor", function()
last_updated_at = last_updated_at
}, results)



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

last_updated_at = "1569453953"
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
}})
json = cjson.encode({
ttl = nil,
files_data = {
{
hash_key="coverband_hash_3_3.coverband_test.runtime../dog.rb.abcd",
meta = {
first_updated_at=first_updated_at,
last_updated_at=last_updated_at,
file="./dog.rb",
file_hash='abcd',
file_length=3
},
coverage = {
['0']= 1,
['1']= 1,
['2']= 1
}
}
}
})
redis.call( 'set', key, json )

call_redis_script('persist-coverage.lua', { key }, {} );
Expand Down