From a14501c61625e7275d5aef734c9f580c82b7c08f Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Mon, 20 Dec 2021 13:27:59 -0500 Subject: [PATCH] Tasks: only execute the event if the plugin is interested in it --- src/lib/Hydra/Event.pm | 6 ++++ src/lib/Hydra/Event/BuildFinished.pm | 5 +++ src/lib/Hydra/Event/BuildQueued.pm | 5 +++ src/lib/Hydra/Event/BuildStarted.pm | 5 +++ src/lib/Hydra/Event/StepFinished.pm | 5 +++ src/lib/Hydra/Plugin.pm | 46 ++++++++++++++++------------ src/lib/Hydra/Plugin/GitInput.pm | 1 - src/lib/Hydra/TaskDispatcher.pm | 10 ++++++ t/Event/BuildFinished.t | 22 +++++++++++++ t/Event/BuildQueued.t | 22 +++++++++++++ t/Event/BuildStarted.t | 22 +++++++++++++ t/Event/StepFinished.t | 22 +++++++++++++ 12 files changed, 150 insertions(+), 21 deletions(-) diff --git a/src/lib/Hydra/Event.pm b/src/lib/Hydra/Event.pm index 938043fa..d7e82758 100644 --- a/src/lib/Hydra/Event.pm +++ b/src/lib/Hydra/Event.pm @@ -38,6 +38,12 @@ sub new_event { }, $self; } +sub interested { + my ($self, $plugin) = @_; + + return $self->{"event"}->interestedIn($plugin); +} + sub execute { my ($self, $db, $plugin) = @_; return $self->{"event"}->execute($db, $plugin); diff --git a/src/lib/Hydra/Event/BuildFinished.pm b/src/lib/Hydra/Event/BuildFinished.pm index 4c4aa647..1c32ec4b 100644 --- a/src/lib/Hydra/Event/BuildFinished.pm +++ b/src/lib/Hydra/Event/BuildFinished.pm @@ -27,6 +27,11 @@ sub new { }, $self; } +sub interestedIn { + my ($self, $plugin) = @_; + return int(defined($plugin->can('buildFinished'))); +} + sub load { my ($self, $db) = @_; diff --git a/src/lib/Hydra/Event/BuildQueued.pm b/src/lib/Hydra/Event/BuildQueued.pm index 551203ad..d164fbc2 100644 --- a/src/lib/Hydra/Event/BuildQueued.pm +++ b/src/lib/Hydra/Event/BuildQueued.pm @@ -25,6 +25,11 @@ sub new { }, $self; } +sub interestedIn { + my ($self, $plugin) = @_; + return int(defined($plugin->can('buildQueued'))); +} + sub load { my ($self, $db) = @_; diff --git a/src/lib/Hydra/Event/BuildStarted.pm b/src/lib/Hydra/Event/BuildStarted.pm index 67fe38ef..182b1770 100644 --- a/src/lib/Hydra/Event/BuildStarted.pm +++ b/src/lib/Hydra/Event/BuildStarted.pm @@ -25,6 +25,11 @@ sub new { }, $self; } +sub interestedIn { + my ($self, $plugin) = @_; + return int(defined($plugin->can('buildStarted'))); +} + sub load { my ($self, $db) = @_; diff --git a/src/lib/Hydra/Event/StepFinished.pm b/src/lib/Hydra/Event/StepFinished.pm index d14423ad..84193cee 100644 --- a/src/lib/Hydra/Event/StepFinished.pm +++ b/src/lib/Hydra/Event/StepFinished.pm @@ -34,6 +34,11 @@ sub new :prototype($$$) { }, $self; } +sub interestedIn { + my ($self, $plugin) = @_; + return int(defined($plugin->can('stepFinished'))); +} + sub load { my ($self, $db) = @_; diff --git a/src/lib/Hydra/Plugin.pm b/src/lib/Hydra/Plugin.pm index a3526427..acefc663 100644 --- a/src/lib/Hydra/Plugin.pm +++ b/src/lib/Hydra/Plugin.pm @@ -25,29 +25,35 @@ sub instantiate { return @$plugins; } -# Called when build $build has been queued. -sub buildQueued { - my ($self, $build) = @_; -} +# To implement behaviors in response to the following events, implement +# the function in your plugin and it will be executed by hydra-notify. +# +# See the tests in t/Event/*.t for arguments, and the documentation for +# notify events for semantics. +# +# # Called when build $build has been queued. +# sub buildQueued { +# my ($self, $build) = @_; +# } -# Called when build $build has started. -sub buildStarted { - my ($self, $build) = @_; -} +# # Called when build $build has started. +# sub buildStarted { +# my ($self, $build) = @_; +# } -# Called when build $build has finished. If the build failed, then -# $dependents is an array ref to a list of builds that have also -# failed as a result (i.e. because they depend on $build or a failed -# dependeny of $build). -sub buildFinished { - my ($self, $build, $dependents) = @_; -} +# # Called when build $build has finished. If the build failed, then +# # $dependents is an array ref to a list of builds that have also +# # failed as a result (i.e. because they depend on $build or a failed +# # dependeny of $build). +# sub buildFinished { +# my ($self, $build, $dependents) = @_; +# } -# Called when step $step has finished. The build log is stored in the -# file $logPath (bzip2-compressed). -sub stepFinished { - my ($self, $step, $logPath) = @_; -} +# # Called when step $step has finished. The build log is stored in the +# # file $logPath (bzip2-compressed). +# sub stepFinished { +# my ($self, $step, $logPath) = @_; +# } # Called to determine the set of supported input types. The plugin # should add these to the $inputTypes hashref, e.g. $inputTypes{'svn'} diff --git a/src/lib/Hydra/Plugin/GitInput.pm b/src/lib/Hydra/Plugin/GitInput.pm index 99d397a6..aca35c30 100644 --- a/src/lib/Hydra/Plugin/GitInput.pm +++ b/src/lib/Hydra/Plugin/GitInput.pm @@ -14,7 +14,6 @@ use Data::Dumper; my $CONFIG_SECTION = "git-input"; - sub supportedInputTypes { my ($self, $inputTypes) = @_; $inputTypes->{'git'} = 'Git checkout'; diff --git a/src/lib/Hydra/TaskDispatcher.pm b/src/lib/Hydra/TaskDispatcher.pm index f23cc814..0a881407 100644 --- a/src/lib/Hydra/TaskDispatcher.pm +++ b/src/lib/Hydra/TaskDispatcher.pm @@ -117,6 +117,11 @@ sub new { type => "counter", help => "Number of tasks that have not been processed because the plugin does not exist." ); + $prometheus->declare( + "notify_plugin_not_interested", + type => "counter", + help => "Number of tasks that have not been processed because the plugin was not interested in the event." + ); my %plugins_by_name = map { ref $_ => $_ } @{$plugins}; @@ -190,6 +195,11 @@ sub dispatch_task { return 0; } + if (!$task->{"event"}->interested($plugin)) { + $self->{"prometheus"}->inc("notify_plugin_not_interested", $event_labels); + return 0; + } + $self->{"prometheus"}->inc("notify_plugin_executions", $event_labels); eval { my $start_time = [gettimeofday()]; diff --git a/t/Event/BuildFinished.t b/t/Event/BuildFinished.t index 298b4162..f0f620ec 100644 --- a/t/Event/BuildFinished.t +++ b/t/Event/BuildFinished.t @@ -54,6 +54,28 @@ my $jobset = createBaseJobset("basic", "basic.nix", $ctx{jobsdir}); ok(evalSucceeds($jobset), "Evaluating jobs/basic.nix should exit with return code 0"); is(nrQueuedBuildsForJobset($jobset), 3, "Evaluating jobs/basic.nix should result in 3 builds"); +subtest "interested" => sub { + my $event = Hydra::Event::BuildFinished->new(123, []); + + subtest "A plugin which does not implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => (); + + is($event->interestedIn($plugin), 0, "The plugin is not interesting."); + }; + + subtest "A plugin which does implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => ( + add => [ + "buildFinished" => sub {} + ] + ); + + is($event->interestedIn($plugin), 1, "The plugin is interesting."); + }; +}; + subtest "load" => sub { my ($build, $dependent_a, $dependent_b) = $db->resultset('Builds')->search( { }, diff --git a/t/Event/BuildQueued.t b/t/Event/BuildQueued.t index 996114b9..a0da54a5 100644 --- a/t/Event/BuildQueued.t +++ b/t/Event/BuildQueued.t @@ -39,6 +39,28 @@ subtest "Parsing build_queued" => sub { ); }; +subtest "interested" => sub { + my $event = Hydra::Event::BuildQueued->new(123, []); + + subtest "A plugin which does not implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => (); + + is($event->interestedIn($plugin), 0, "The plugin is not interesting."); + }; + + subtest "A plugin which does implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => ( + add => [ + "buildQueued" => sub {} + ] + ); + + is($event->interestedIn($plugin), 1, "The plugin is interesting."); + }; +}; + subtest "load" => sub { my $build = $builds->{"empty_dir"}; diff --git a/t/Event/BuildStarted.t b/t/Event/BuildStarted.t index 08433d8d..c8ddbbf1 100644 --- a/t/Event/BuildStarted.t +++ b/t/Event/BuildStarted.t @@ -45,6 +45,28 @@ subtest "Parsing build_started" => sub { ); }; +subtest "interested" => sub { + my $event = Hydra::Event::BuildStarted->new(123, []); + + subtest "A plugin which does not implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => (); + + is($event->interestedIn($plugin), 0, "The plugin is not interesting."); + }; + + subtest "A plugin which does implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => ( + add => [ + "buildStarted" => sub {} + ] + ); + + is($event->interestedIn($plugin), 1, "The plugin is interesting."); + }; +}; + subtest "load" => sub { my $build = $db->resultset('Builds')->search( { }, diff --git a/t/Event/StepFinished.t b/t/Event/StepFinished.t index ae2d8081..08726566 100644 --- a/t/Event/StepFinished.t +++ b/t/Event/StepFinished.t @@ -64,6 +64,28 @@ subtest "Parsing step_finished" => sub { ); }; +subtest "interested" => sub { + my $event = Hydra::Event::StepFinished->new(123, []); + + subtest "A plugin which does not implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => (); + + is($event->interestedIn($plugin), 0, "The plugin is not interesting."); + }; + + subtest "A plugin which does implement the API" => sub { + my $plugin = {}; + my $mock = mock_obj $plugin => ( + add => [ + "stepFinished" => sub {} + ] + ); + + is($event->interestedIn($plugin), 1, "The plugin is interesting."); + }; +}; + subtest "load" => sub { my $step = $db->resultset('BuildSteps')->search(