Skip to content

Commit 596f676

Browse files
committed
Emit restart events when job restarted automatically
TBD Using the `restart_openqa_job` from the Restart module should not duplicate the event which is emitted by the API, which also invoke `auto_duplicate`. And it should also trigger the event when the job is processed and not while is queued. That should make sure that the event is send to AMQP for jobs with `RETRY` once it is actually triggered. Load AMQP plugin into the Gru tasks Makes possible to the minion tasks to emit events, as it makes the AMQP plugin available in its context. The `one_tick` is called to trigger the `next_tick` in the `register` function of the AMPQ module immediately, otherwise it seems like it is registered late and the event is not emitted. issue: https://progress.opensuse.org/issues/190557 Signed-off-by: Ioannis Bonatakis <[email protected]>
1 parent 1801a6d commit 596f676

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

lib/OpenQA/Shared/Plugin/Gru.pm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ sub register ($self, $app, $config) {
9898
});
9999

100100
$self->register_tasks;
101+
my $plugins = $app->config->{global}->{plugins};
102+
if (defined $plugins && $plugins =~ /\bAMQP\b/) {
103+
push @{$app->plugins->namespaces}, 'OpenQA::WebAPI::Plugin' # uncoverable statement
104+
unless grep { $_ eq 'OpenQA::WebAPI::Plugin' } @{$app->plugins->namespaces};
105+
106+
try {
107+
$app->plugin('AMQP');
108+
Mojo::IOLoop->singleton->one_tick; # handle async plugin registration
109+
}
110+
catch ($e) {
111+
log_error("Failed to load AMQP plugin for Gru: $e");
112+
}
113+
}
101114

102115
# Enable the Minion Admin interface under /minion
103116
my $auth = $app->routes->under('/minion')->to('session#ensure_admin');

lib/OpenQA/Task/Job/Restart.pm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package OpenQA::Task::Job::Restart;
55
use Mojo::Base 'Mojolicious::Plugin', -signatures;
66

77
use Time::Seconds;
8+
use OpenQA::Events;
89

910
sub register ($self, $app, @args) {
1011
$app->minion->add_task(restart_job => \&_restart_job);
@@ -17,6 +18,12 @@ sub restart_delay { $ENV{OPENQA_JOB_RESTART_DELAY} // 5 }
1718
sub restart_openqa_job ($minion_job, $openqa_job) {
1819
my $cloned_job_or_error = $openqa_job->auto_duplicate;
1920
my $is_ok = ref $cloned_job_or_error || $cloned_job_or_error =~ qr/(already.*clone|direct parent)/i;
21+
if ($is_ok) {
22+
my $openqa_job_id = $openqa_job->id;
23+
my %event_data = (id => $openqa_job_id, result => $cloned_job_or_error, auto => 1);
24+
OpenQA::Events->singleton->emit_event('openqa_job_restart', data => \%event_data);
25+
}
26+
2027
$minion_job->note(
2128
ref $cloned_job_or_error
2229
? (cluster_cloned => $cloned_job_or_error->{cluster_cloned})

t/10-jobs.t

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use OpenQA::Jobs::Constants;
1919
use OpenQA::Test::Case;
2020
use Test::MockModule 'strict';
2121
use Test::Mojo;
22+
use Test::Output;
2223
use Test::Warnings qw(:report_warnings warning);
2324
use Mojo::File 'path';
2425
use Mojo::JSON qw(decode_json encode_json);
@@ -899,7 +900,8 @@ subtest 'job setting based retriggering' => sub {
899900
my $finalize_job_count_before = @{$get_jobs->('finalize_job_results')};
900901
$job->update({state => SCHEDULED, result => NONE});
901902
$job->done(result => FAILED);
902-
perform_minion_jobs($minion);
903+
stdout_like { perform_minion_jobs($minion) } qr/Job \d+ duplicated as \d+/,
904+
'check debug message from auto_duplicate';
903905
is $jobs->count, $jobs_nr + 2, 'job retriggered as it FAILED (with retry)';
904906
$job->update;
905907
$job->discard_changes;
@@ -931,6 +933,32 @@ subtest 'job setting based retriggering' => sub {
931933
is $lastest_job->latest_job->id, $lastest_job->id, 'found the latest job from latest job itself';
932934
};
933935

936+
subtest 'AMQP event emission for minion restarts' => sub {
937+
my $events_module = Test::MockModule->new('OpenQA::Events');
938+
my @emitted_events;
939+
$events_module->redefine(
940+
emit_event => sub ($self, $event_type, %args) {
941+
push @emitted_events, {type => $event_type, data => $args{data}};
942+
$events_module->original('emit_event')->($self, $event_type, %args);
943+
});
944+
945+
my $minion = $t->app->minion;
946+
my %_settings = %settings;
947+
$_settings{TEST} = 'test_restart';
948+
$_settings{RETRY} = '1';
949+
my $job = _job_create(\%_settings);
950+
my $job_id = $job->id;
951+
952+
@emitted_events = ();
953+
$job->done(result => FAILED);
954+
stdout_like { perform_minion_jobs($minion) } qr/Job \d+ duplicated as \d+/;
955+
my @restart_events = grep { $_->{type} eq 'openqa_job_restart' } @emitted_events;
956+
is scalar(@restart_events), 1, 'exactly one job restart event emitted';
957+
my $event_data = $restart_events[0]->{data};
958+
is $event_data->{id}, $job_id, 'event contains original job ID';
959+
ok exists($event_data->{result}), 'event contains result';
960+
};
961+
934962
subtest '"race" between status updates and stale job detection' => sub {
935963
my $job = $jobs->create({TEST => 'test-job'});
936964
is_deeply $job->update_status({}), {result => 0}, 'status update rejected for scheduled job';

0 commit comments

Comments
 (0)