File: report_distributor.rb

package info (click to toggle)
ruby-knapsack 1.18.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 1,084 kB
  • sloc: ruby: 2,832; makefile: 4; sh: 3
file content (92 lines) | stat: -rw-r--r-- 2,865 bytes parent folder | download
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