require 'gorgon/host_state' require 'observer' module Gorgon class JobState include Observable attr_reader :total_files, :remaining_files_count, :state, :crashed_hosts def initialize total_files @total_files = total_files @remaining_files_count = total_files @failed_tests = [] @crashed_hosts = [] @hosts = {} if @remaining_files_count > 0 @state = :starting else @state = :complete end end def failed_files_count @failed_tests.count end def finished_files_count total_files - remaining_files_count end def file_started payload raise_if_completed if @state == :starting @state = :running end file_started_update_host_state payload changed notify_observers payload end def file_finished payload raise_if_completed @remaining_files_count -= 1 @state = :complete if @remaining_files_count == 0 handle_failed_test payload if failed_test?(payload) @hosts[payload[:hostname]].file_finished payload[:worker_id], payload[:filename] changed notify_observers payload end def gorgon_crash_message payload @crashed_hosts << payload[:hostname] changed notify_observers payload end def cancel @remaining_files_count = 0 @state = :cancelled changed notify_observers({}) end def each_failed_test @failed_tests.each do |test| yield test end end def each_running_file @hosts.each do |hostname, host| host.each_running_file do |filename| yield hostname, filename end end end def total_running_hosts @hosts.size end def total_running_workers result = 0 @hosts.each do |hostname, host| result += host.total_running_workers end result end def is_job_complete? @state == :complete end def is_job_cancelled? @state == :cancelled end private def file_started_update_host_state payload hostname = payload[:hostname] @hosts[hostname] = HostState.new if @hosts[hostname].nil? @hosts[hostname].file_started payload[:worker_id], payload[:filename] end def handle_failed_test payload @failed_tests << payload end def raise_if_completed # TODO: Following should raise a specific error instead of a generic RuntimeError raise "JobState#file_finished called when job was already complete" if is_job_complete? puts "NOTICE: JobState#file_finished called after job was cancelled" if is_job_cancelled? end def failed_test? payload payload[:type] == "fail" || payload[:type] == "crash" end end end