From 01fb29ed1b9b3e046976bcd123ecfa8de87e649a Mon Sep 17 00:00:00 2001 From: Yuri Rudman Date: Tue, 18 Apr 2017 10:53:34 -0400 Subject: [PATCH 1/2] fixed bug introduced by removing agent_class attribute: timeout was not executed for failed Image Scanning job. Fixes #14788 --- app/models/job.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/job.rb b/app/models/job.rb index a552be0ae29..ee0e60d48f8 100644 --- a/app/models/job.rb +++ b/app/models/job.rb @@ -165,7 +165,9 @@ def self.check_jobs_for_timeout # Allow jobs to run longer if the MiqQueue task is still active. (Limited to MiqServer for now.) # TODO: can we add method_name, queue_name, role, instance_id to the exists? - next if MiqQueue.exists?(:state => %w(dequeue ready), :task_id => job.guid) + if job.miq_server_id + next if MiqQueue.exists?(:state => %w(dequeue ready), :task_id => job.guid, :class_name => "MiqServer") + end job.timeout! end rescue Exception From abaf45640fe9147bcc74989a431e892a924cb51c Mon Sep 17 00:00:00 2001 From: Yuri Rudman Date: Wed, 19 Apr 2017 15:07:06 -0400 Subject: [PATCH 2/2] added test coverage for .check_jobs_for_timeout and .timeout! --- spec/models/job_spec.rb | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/spec/models/job_spec.rb b/spec/models/job_spec.rb index d9e00d00ca4..c2f117bf172 100644 --- a/spec/models/job_spec.rb +++ b/spec/models/job_spec.rb @@ -272,6 +272,51 @@ end end end + + describe "#timeout!" do + it "adds to MiqQueue signal 'signal_abort' for this job " do + @job.timeout! + expect_signal_abort_and_timeout_message + end + end + + describe ".check_jobs_for_timeout" do + before(:each) do + @job.update_attributes(:state => "active") + @queue_item = MiqQueue.put(:task_id => @job.guid) + end + + context "job timed out" do + it "calls 'job#timeout!' if server was not assigned to job" do + Timecop.travel 5.minutes + Job.check_jobs_for_timeout + expect_signal_abort_and_timeout_message + end + + it "calls 'job#timeout!' if server was assigned to job but queue item not in 'ready' or 'dequeue' state" do + @queue_item.update_attributes(:state => MiqQueue::STATE_WARN, :class_name => "MiqServer") + @job.update_attributes(:miq_server_id => @server1.id) + Timecop.travel 5.minutes + Job.check_jobs_for_timeout + expect_signal_abort_and_timeout_message + end + + it "does not call 'job#timeout!' if queue state is 'ready' and server was assigned to job" do + @queue_item.update_attributes(:state => MiqQueue::STATE_READY, :class_name => "MiqServer") + @job.update_attributes(:miq_server_id => @server1.id) + Timecop.travel 5.minutes + Job.check_jobs_for_timeout + expect_no_signal_abort + end + end + + context "job not timed out" do + it "does not call 'job#timeout!'" do + Job.check_jobs_for_timeout + expect_no_signal_abort + end + end + end end context "before_destroy callback" do @@ -372,6 +417,16 @@ private + def expect_signal_abort_and_timeout_message + queue_item = MiqQueue.find_by(:instance_id => @job.id, :class_name => "Job", :method_name => "signal_abort") + expect(queue_item.args[0].starts_with?("job timed out after")).to be true + end + + def expect_no_signal_abort + queue_item = MiqQueue.find_by(:instance_id => @job.id, :class_name => "Job", :method_name => "signal_abort") + expect(queue_item).to be nil + end + def assert_queue_message expect(MiqQueue.count).to eq(1) q = MiqQueue.first