-
Notifications
You must be signed in to change notification settings - Fork 303
[WIP] Put katello event queue handler back into Dynflow #11363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| module Actions | ||
| module Katello | ||
| module EventQueue | ||
| class Monitor < Actions::EntryAction | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Iirc foreman-maintain performs checks for long running tasks before upgrade, we'll probably need to whitelist this new action in there. |
||
| include ::Dynflow::Action::Singleton | ||
| include ::Dynflow::Action::Polling | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless stated otherwise, actions use the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should be OK in combination with your prior point: instead of using a Poll -> Handle ping-pong the Poll will fully drain the queue in a loop which can be broken early with |
||
| def self.launch(world) | ||
| unless self.singleton_locked?(world) | ||
| ForemanTasks.trigger(self) | ||
| end | ||
| end | ||
|
|
||
| def invoke_external_task | ||
| ::Katello::EventQueue.initialize | ||
| action_logger.info "Katello Event Queue initialized" | ||
| end | ||
|
|
||
| def run(event = nil) | ||
jturel marked this conversation as resolved.
Show resolved
Hide resolved
jturel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| case event | ||
| when Skip | ||
| # noop | ||
| else | ||
| super | ||
| end | ||
| end | ||
|
|
||
| def stop_condition | ||
| -> { world.terminating? } | ||
| end | ||
|
|
||
| def poll_external_task | ||
| poller = ::Katello::EventMonitor::PollerThread.new | ||
| User.as_anonymous_admin do | ||
| poller.drain_queue(-> { world.terminating? }) | ||
| end | ||
| end | ||
|
|
||
| def done? | ||
| false | ||
| end | ||
|
|
||
| def poll_intervals | ||
| [2] | ||
| end | ||
|
|
||
| def rescue_strategy | ||
| ::Dynflow::Action::Rescue::Skip | ||
| end | ||
|
|
||
| def humanized_name | ||
| _("Katello Event Queue") | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,6 +77,14 @@ class Engine < ::Rails::Engine | |
| ForemanTasks.dynflow.eager_load_actions! | ||
| end | ||
|
|
||
| initializer "katello.start_katello_events", before: :finisher_hook do | ||
| unless Rails.env.test? | ||
| ForemanTasks.dynflow.config.post_executor_init do |world| | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if the action stops/pauses/whatever, the event queue won't be processed until the |
||
| Actions::Katello::EventQueue::Monitor.launch(world) | ||
| end | ||
| end | ||
| end | ||
|
|
||
| # make sure the Katello plugin is initialized before `after_initialize` | ||
| # hook so that the resumed Dynflow tasks can rely on everything ready. | ||
| initializer 'katello.register_plugin', :before => :finisher_hook, :after => 'foreman_remote_execution.register_plugin' do |app| | ||
|
|
@@ -147,7 +155,6 @@ class Engine < ::Rails::Engine | |
| end | ||
|
|
||
| Katello::EventDaemon::Runner.register_service(:candlepin_events, Katello::CandlepinEventListener) | ||
| Katello::EventDaemon::Runner.register_service(:katello_events, Katello::EventMonitor::PollerThread) | ||
|
|
||
| # Lib Extensions | ||
| ::Foreman::Renderer::Scope::Variables::Base.include Katello::Concerns::RendererExtensions | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| require 'katello_test_helper' | ||
|
|
||
| module ::Actions::Katello::EventQueue | ||
| class MonitorTest < ActiveSupport::TestCase | ||
| include Dynflow::Testing | ||
|
|
||
| class ::Dynflow::Testing::DummyCoordinator | ||
| def find_locks(_filter) | ||
| [] | ||
| end | ||
|
|
||
| def acquire(_lock) | ||
| true | ||
| end | ||
| end | ||
|
|
||
| let(:action_class) { ::Actions::Katello::EventQueue::Monitor } | ||
|
|
||
| let(:planned_action) do | ||
| action = create_action action_class | ||
| plan_action action | ||
| end | ||
|
|
||
| let(:running_action) do | ||
| Katello::EventQueue.expects(:initialize) | ||
|
|
||
| run_action planned_action | ||
| end | ||
|
|
||
| def test_run | ||
| Katello::EventMonitor::PollerThread.any_instance.expects(:drain_queue) | ||
|
|
||
| progress_action_time running_action | ||
|
|
||
| assert_equal :suspended, running_action.state | ||
| assert_nil running_action.output[:last_error] | ||
| end | ||
|
|
||
| def test_run_error | ||
| Katello::EventMonitor::PollerThread.any_instance.stubs(:drain_queue).raises(StandardError) | ||
|
|
||
| progress_action_time running_action | ||
|
|
||
| assert_equal :suspended, running_action.state | ||
| assert_equal event.id, running_action.output.dig(:last_error, :handler, :event, :id) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| FactoryBot.define do | ||
| factory :katello_event, class: Katello::Event do | ||
| trait :in_progress do | ||
| in_progress { true } | ||
| end | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default rescue_strategy is to pause the action. Iirc paused actions still hold the singleton lock. Using any of the other two strategies which would cause the lock to be unlocked on failure would probably be better idea for more hands-off operation.