require "gorgon/configuration" require "gorgon/amqp_service" require 'gorgon/callback_handler' require "gorgon/g_logger" require "uuidtools" require "awesome_print" require "socket" module WorkUnit def self.run_file filename require "gorgon/testunit_runner" start_t = Time.now begin failures = TestRunner.run_file(filename) length = Time.now - start_t if failures.empty? results = {:failures => [], :type => :pass, :time => length} else results = {:failures => failures, :type => :fail, :time => length} end rescue Exception => e results = {:failures => ["Exception: #{e.message}\n#{e.backtrace.join("\n")}"], :type => :crash, :time => (Time.now - start_t)} end return results end end class Worker include GLogger def self.build(config) payload = Yajl::Parser.new(:symbolize_keys => true).parse($stdin.read) job_definition = JobDefinition.new(payload) connection_config = config[:connection] amqp = AmqpService.new connection_config callback_handler = CallbackHandler.new(job_definition.callbacks) worker_id = UUIDTools::UUID.timestamp_create.to_s ENV["GORGON_WORKER_ID"] = worker_id params = { :amqp => amqp, :file_queue_name => job_definition.file_queue_name, :reply_exchange_name => job_definition.reply_exchange_name, :worker_id => worker_id, :test_runner => WorkUnit, :callback_handler => callback_handler, :log_file => config[:log_file] } new(params) end def initialize(params) initialize_logger params[:log_file] @amqp = params[:amqp] @file_queue_name = params[:file_queue_name] @reply_exchange_name = params[:reply_exchange_name] @worker_id = params[:worker_id] @test_runner = params[:test_runner] @callback_handler = params[:callback_handler] end def work log "Running before_start callback..." @callback_handler.before_start log "Running files ..." @amqp.start_worker @file_queue_name, @reply_exchange_name do |queue, exchange| while filename = queue.pop exchange.publish make_start_message(filename) log "Running '#{filename}'" test_results = run_file(filename) exchange.publish make_finish_message(filename, test_results) end end ensure # this 'ensure' that we run after_complete even after an 'INT' signal clean_up end private def clean_up log "Running after_complete callback" @callback_handler.after_complete end def run_file(filename) @test_runner.run_file(filename) end def make_start_message(filename) {:action => :start, :hostname => Socket.gethostname, :worker_id => @worker_id, :filename => filename} end def make_finish_message(filename, results) {:action => :finish, :hostname => Socket.gethostname, :worker_id => @worker_id, :filename => filename}.merge(results) end end