Class: Hydra::Master
- Inherits:
-
Object
- Object
- Hydra::Master
- Includes:
- Hydra::Messages::Master, Open3
- Defined in:
- lib/hydra/master.rb
Instance Attribute Summary collapse
-
#failed_files ⇒ Object
readonly
Returns the value of attribute failed_files.
-
#report_text ⇒ Object
readonly
A text report of the time it took to run each file.
Instance Method Summary collapse
-
#initialize(opts = { }) ⇒ Master
constructor
Create a new Master.
-
#process_results(worker, message) ⇒ Object
Process the results coming back from the worker.
-
#send_file(worker) ⇒ Object
Send a file down to a worker.
-
#worker_begin(worker) ⇒ Object
Message handling.
Constructor Details
#initialize(opts = { }) ⇒ Master
Create a new Master
Options:
-
:files
-
An array of test files to be run. These should be relative paths from the root of the project, since they may be run on different machines which may have different paths.
-
-
:workers
-
An array of hashes. Each hash should be the configuration options for a worker.
-
-
:listeners
-
An array of Hydra::Listener objects. See Hydra::Listener::MinimalOutput for an example listener
-
-
:verbose
-
Set to true to see lots of Hydra output (for debugging)
-
-
:autosort
-
Set to false to disable automatic sorting by historical run-time per file
-
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 93 94 |
# File 'lib/hydra/master.rb', line 36 def initialize(opts = { }) opts.stringify_keys! config_file = opts.delete('config') { nil } if config_file begin config_erb = ERB.new(IO.read(config_file)).result(binding) rescue Exception => e raise(YmlLoadError,"config file was found, but could not be parsed with ERB.\n#{$!.inspect}") end begin config_yml = YAML::load(config_erb) rescue StandardError => e raise(YmlLoadError,"config file was found, but could not be parsed.\n#{$!.inspect}") end opts.merge!(config_yml.stringify_keys!) end @files = Array(opts.fetch('files') { nil }) raise "No files, nothing to do" if @files.empty? @incomplete_files = @files.dup @failed_files = [] @workers = [] @listeners = [] @event_listeners = Array(opts.fetch('listeners') { nil } ) @event_listeners.select{|l| l.is_a? String}.each do |l| @event_listeners.delete_at(@event_listeners.index(l)) listener = eval(l) @event_listeners << listener if listener.is_a?(Hydra::Listener::Abstract) end @string_runner_event_listeners = Array( opts.fetch( 'runner_listeners' ) { nil } ) @runner_log_file = opts.fetch('runner_log_file') { nil } @verbose = opts.fetch('verbose') { false } @autosort = opts.fetch('autosort') { true } @sync = opts.fetch('sync') { nil } @environment = opts.fetch('environment') { 'test' } @options = opts.fetch('options') { '' } if @autosort sort_files_from_report @event_listeners << Hydra::Listener::ReportGenerator.new(File.new(heuristic_file, 'w')) end # default is one worker that is configured to use a pipe with one runner worker_cfg = opts.fetch('workers') { [ { 'type' => 'local', 'runners' => 1} ] } trace "Initialized" trace " Files: (#{@files.inspect})" trace " Workers: (#{worker_cfg.inspect})" trace " Verbose: (#{@verbose.inspect})" @event_listeners.each{|l| l.testing_begin(@files) } boot_workers worker_cfg end |
Instance Attribute Details
#failed_files ⇒ Object (readonly)
Returns the value of attribute failed_files.
17 18 19 |
# File 'lib/hydra/master.rb', line 17 def failed_files @failed_files end |
#report_text ⇒ Object (readonly)
A text report of the time it took to run each file
142 143 144 |
# File 'lib/hydra/master.rb', line 142 def report_text @report_text end |
Instance Method Details
#process_results(worker, message) ⇒ Object
Process the results coming back from the worker.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/hydra/master.rb', line 114 def process_results(worker, ) if .output =~ /ActiveRecord::StatementInvalid(.*)[Dd]eadlock/ or .output =~ /PGError: ERROR(.*)[Dd]eadlock/ or .output =~ /Mysql::Error: SAVEPOINT(.*)does not exist: ROLLBACK/ or .output =~ /Mysql::Error: Deadlock found/ trace "Deadlock detected running [#{.file}]. Will retry at the end" @files.push(.file) send_file(worker) else @incomplete_files.delete_at(@incomplete_files.index(.file)) trace "#{@incomplete_files.size} Files Remaining" @event_listeners.each{|l| l.file_end(.file, .output) } unless .output == '.' @failed_files << .file end if @incomplete_files.empty? @workers.each do |worker| @event_listeners.each{|l| l.worker_end(worker) } end shutdown_all_workers else send_file(worker) end end end |
#send_file(worker) ⇒ Object
Send a file down to a worker.
102 103 104 105 106 107 108 109 110 111 |
# File 'lib/hydra/master.rb', line 102 def send_file(worker) f = @files.shift if f trace "Sending #{f.inspect}" @event_listeners.each{|l| l.file_begin(f) } worker[:io].write(RunFile.new(:file => f)) else trace "No more files to send" end end |
#worker_begin(worker) ⇒ Object
Message handling
97 98 99 |
# File 'lib/hydra/master.rb', line 97 def worker_begin(worker) @event_listeners.each {|l| l.worker_begin(worker) } end |