1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
module Knapsack
module Distributors
class ReportDistributor < BaseDistributor
def sorted_report
@sorted_report ||= report.sort_by { |test_path, time| time }.reverse
end
def sorted_report_with_existing_tests
@sorted_report_with_existing_tests ||= sorted_report.select { |test_path, time| all_tests.include?(test_path) }
end
def total_time_execution
@total_time_execution ||= sorted_report_with_existing_tests.map(&:last).reduce(0, :+).to_f
end
def node_time_execution
@node_time_execution ||= total_time_execution / ci_node_total
end
private
def post_assign_test_files_to_node
assign_slow_test_files
assign_remaining_test_files
sort_assigned_test_files
end
def sort_assigned_test_files
ci_node_total.times do |index|
# sort by first key (file name)
# reverse it and then sort by second key (time) in reverse order
node_tests[index][:test_files_with_time].sort!.reverse!.sort! do |x, y|
y[1] <=> x[1]
end
end
end
def post_tests_for_node(node_index)
node_test = node_tests[node_index]
return unless node_test
node_test[:test_files_with_time].map(&:first)
end
def default_node_tests
@node_tests = []
ci_node_total.times do |index|
@node_tests << {
node_index: index,
time_left: node_time_execution,
test_files_with_time: []
}
end
end
def assign_slow_test_files
@not_assigned_test_files = []
node_index = 0
sorted_report_with_existing_tests.each do |test_file_with_time|
assign_slow_test_file(node_index, test_file_with_time)
node_index += 1
node_index %= ci_node_total
end
end
def assign_slow_test_file(node_index, test_file_with_time)
time = test_file_with_time[1]
time_left = node_tests[node_index][:time_left] - time
if time_left >= 0 or node_tests[node_index][:test_files_with_time].empty?
node_tests[node_index][:time_left] -= time
node_tests[node_index][:test_files_with_time] << test_file_with_time
else
@not_assigned_test_files << test_file_with_time
end
end
def assign_remaining_test_files
@not_assigned_test_files.each do |test_file_with_time|
index = node_with_max_time_left
time = test_file_with_time[1]
node_tests[index][:time_left] -= time
node_tests[index][:test_files_with_time] << test_file_with_time
end
end
def node_with_max_time_left
node_test = node_tests.max { |a,b| a[:time_left] <=> b[:time_left] }
node_test[:node_index]
end
end
end
end
|