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
-
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 95 96 97 98 |
# File 'lib/hydra/master.rb', line 38 def initialize(opts = { }) $stdout = ThreadsafeIO.new($stdout) 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 = ProxyConfig.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' } 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.
19 20 21 |
# File 'lib/hydra/master.rb', line 19 def failed_files @failed_files end |
#report_text ⇒ Object (readonly)
A text report of the time it took to run each file
146 147 148 |
# File 'lib/hydra/master.rb', line 146 def report_text @report_text end |
Instance Method Details
#process_results(worker, message) ⇒ Object
Process the results coming back from the worker.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/hydra/master.rb', line 118 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.
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/hydra/master.rb', line 106 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
101 102 103 |
# File 'lib/hydra/master.rb', line 101 def worker_begin(worker) @event_listeners.each {|l| l.worker_begin(worker) } end |