Revision e5b4634f
Added by Adam Ruzicka almost 6 years ago
app/jobs/application_job.rb | ||
---|---|---|
def humanized_name
|
||
self.class.name
|
||
end
|
||
|
||
def self.spawn_if_missing(world)
|
||
return if (Foreman.in_rake? && !Foreman.in_rake?('dynflow:executor')) || Rails.env.test?
|
||
|
||
pending_jobs = world.persistence.find_execution_plans(filters: { :state => 'scheduled' })
|
||
scheduled_job = pending_jobs.select do |job|
|
||
delayed_plan = world.persistence.load_delayed_plan job.id
|
||
next unless delayed_plan.present?
|
||
arg = delayed_plan.to_hash[:serialized_args].first
|
||
arg.is_a?(Hash) && arg['job_class'] == self.to_s
|
||
end
|
||
|
||
# Schedule the job only if it doesn't exit yet
|
||
self.perform_later if scheduled_job.blank?
|
||
end
|
||
end
|
config/initializers/rss_notifications.rb | ||
---|---|---|
# First, we check if there's a job already enqueued for RSS notifications
|
||
::Foreman::Application.dynflow.config.on_init do |world|
|
||
pending_jobs = world.persistence.find_execution_plans(filters: { :state => 'scheduled' })
|
||
scheduled_job = pending_jobs.select do |job|
|
||
delayed_plan = world.persistence.load_delayed_plan job.id
|
||
next unless delayed_plan.present?
|
||
delayed_plan.to_hash[:serialized_args].first.try(:[], 'job_class') == 'CreateRssNotifications'
|
||
end
|
||
|
||
# Only create notifications if there isn't a scheduled job
|
||
CreateRssNotifications.perform_later if !Rails.env.test? && scheduled_job.blank?
|
||
CreateRssNotifications.spawn_if_missing(world)
|
||
end
|
test/unit/application_job_test.rb | ||
---|---|---|
require 'test_helper'
|
||
require 'ostruct'
|
||
|
||
class ApplicationJobTest < ActiveSupport::TestCase
|
||
describe '.spawn_if_missing' do
|
||
# Force world initialization before stubbing,
|
||
# otherwise CreateRssNotifications would be triggered
|
||
# on first call to world
|
||
before { world }
|
||
|
||
let(:job_class) { ApplicationJob }
|
||
let(:world) { Foreman::Application.dynflow.world }
|
||
|
||
def stub_delayed_plans_with_serialized_args(*args)
|
||
execution_plans = args.each_with_index.map { |_, index| OpenStruct.new(:id => index) }
|
||
world.persistence.expects(:find_execution_plans).returns(execution_plans)
|
||
args.each_with_index do |arg, index|
|
||
delayed_plan = OpenStruct.new(:to_hash => { :serialized_args => arg })
|
||
world.persistence.expects(:load_delayed_plan).with(index).returns(delayed_plan)
|
||
end
|
||
end
|
||
|
||
describe 'when in rake' do
|
||
before { Foreman.expects(:in_rake?).returns(true) }
|
||
|
||
it 'runs in dynflow:executor rake task' do
|
||
Foreman.expects(:in_rake?).with('dynflow:executor').returns(true)
|
||
Rails.env.expects(:test?).returns(false)
|
||
job_class.expects(:perform_later)
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
|
||
it 'does not run in other rake tasks' do
|
||
Foreman.expects(:in_rake?).with('dynflow:executor').returns(false)
|
||
Rails.env.expects(:test?).never
|
||
job_class.expects(:perform_later).never
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
end
|
||
|
||
describe 'when not in rake' do
|
||
before { Foreman.expects(:in_rake?).returns(false) }
|
||
|
||
it 'does not run in test environment' do
|
||
Rails.env.expects(:test?).returns(true)
|
||
job_class.expects(:perform_later).never
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
|
||
describe 'when not in test environment' do
|
||
before { Rails.env.expects(:test?).returns(false) }
|
||
|
||
it 'runs' do
|
||
job_class.expects(:perform_later)
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
|
||
it 'does not trigger the job if it already exists' do
|
||
stub_delayed_plans_with_serialized_args [{ 'job_class' => job_class.to_s }]
|
||
job_class.expects(:perform_later).never
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
|
||
it 'ignores other active jobs' do
|
||
stub_delayed_plans_with_serialized_args [{ 'job_class' => 'NotTheClassWeAreLookingFor' }]
|
||
job_class.expects(:perform_later)
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
|
||
it 'does not crash when delayed jobs have unexpected arguments' do
|
||
stub_delayed_plans_with_serialized_args [1]
|
||
job_class.expects(:perform_later)
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
|
||
it 'does not crash when delayed jobs have unexpected shape of arguments' do
|
||
stub_delayed_plans_with_serialized_args [{'something' => 'not important' }]
|
||
job_class.expects(:perform_later)
|
||
|
||
job_class.spawn_if_missing world
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
Also available in: Unified diff
The root cause was we were triggering the active jobs too early,
sometimes even before the db was migrated. This led to all sorts of
errors. The provided helper method does not trigger the jobs when in
any rake or in test environment. This helper should be reused in
Katello as well.