From a12e9478e76400881e9c0d12c5dd6e4a218652ee Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 24 Oct 2016 20:20:20 +0200 Subject: [PATCH] When manually scheduling an eval, force re-instantiation of store derivations Without this, if (failed or aborted) derivations have been garbage-collected, there is no way to restart them, which is very annoying. Now we set a forceEval flag in the jobset to cause it to be re-evaluated even if none of the inputs have changed. --- src/lib/Hydra/Controller/API.pm | 9 +++++---- src/lib/Hydra/Schema/Jobsets.pm | 11 +++++++++-- src/script/hydra-eval-jobset | 4 ++-- src/sql/hydra.sql | 1 + src/sql/upgrade-51.sql | 1 + 5 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 src/sql/upgrade-51.sql diff --git a/src/lib/Hydra/Controller/API.pm b/src/lib/Hydra/Controller/API.pm index 7c74a651..1ee85923 100644 --- a/src/lib/Hydra/Controller/API.pm +++ b/src/lib/Hydra/Controller/API.pm @@ -202,10 +202,11 @@ sub scmdiff : Chained('api') PathPart('scmdiff') Args(0) { sub triggerJobset { - my ($self, $c, $jobset) = @_; + my ($self, $c, $jobset, $force) = @_; print STDERR "triggering jobset ", $jobset->project->name . ":" . $jobset->name, "\n"; txn_do($c->model('DB')->schema, sub { $jobset->update({ triggertime => time }); + $jobset->update({ forceeval => 1 }) if $force; }); push @{$c->{stash}->{json}->{jobsetsTriggered}}, $jobset->project->name . ":" . $jobset->name; } @@ -222,12 +223,12 @@ sub push : Chained('api') PathPart('push') Args(0) { my ($p, $j) = parseJobsetName($s); my $jobset = $c->model('DB::Jobsets')->find($p, $j); next unless defined $jobset && ($force || ($jobset->project->enabled && $jobset->enabled)); - triggerJobset($self, $c, $jobset); + triggerJobset($self, $c, $jobset, $force); } my @repos = split /,/, ($c->request->query_params->{repos} // ""); foreach my $r (@repos) { - triggerJobset($self, $c, $_) foreach $c->model('DB::Jobsets')->search( + triggerJobset($self, $c, $_, $force) foreach $c->model('DB::Jobsets')->search( { 'project.enabled' => 1, 'me.enabled' => 1 }, { join => 'project' , where => \ [ 'exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value = ?)', [ 'value', $r ] ] @@ -251,7 +252,7 @@ sub push_github : Chained('api') PathPart('push-github') Args(0) { my $repo = $in->{repository}->{name} or die; print STDERR "got push from GitHub repository $owner/$repo\n"; - triggerJobset($self, $c, $_) foreach $c->model('DB::Jobsets')->search( + triggerJobset($self, $c, $_, 0) foreach $c->model('DB::Jobsets')->search( { 'project.enabled' => 1, 'me.enabled' => 1 }, { join => 'project' , where => \ [ 'exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value like ?)', [ 'value', "%github.com%$owner/$repo%" ] ] diff --git a/src/lib/Hydra/Schema/Jobsets.pm b/src/lib/Hydra/Schema/Jobsets.pm index 682b3ab0..965ffcfc 100644 --- a/src/lib/Hydra/Schema/Jobsets.pm +++ b/src/lib/Hydra/Schema/Jobsets.pm @@ -129,6 +129,11 @@ __PACKAGE__->table("Jobsets"); data_type: 'text' is_nullable: 1 +=head2 forceeval + + data_type: 'boolean' + is_nullable: 1 + =cut __PACKAGE__->add_columns( @@ -166,6 +171,8 @@ __PACKAGE__->add_columns( { data_type => "integer", default_value => 100, is_nullable => 0 }, "fetcherrormsg", { data_type => "text", is_nullable => 1 }, + "forceeval", + { data_type => "boolean", is_nullable => 1 }, ); =head1 PRIMARY KEY @@ -338,8 +345,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07043 @ 2015-07-30 16:52:20 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Coci9FdBAvUO9T3st2NEqA +# Created by DBIx::Class::Schema::Loader v0.07045 @ 2016-10-24 20:12:51 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:PSR66NnVRNTMFhDEm10erA my %hint = ( columns => [ diff --git a/src/script/hydra-eval-jobset b/src/script/hydra-eval-jobset index ba478f6a..afbbea91 100755 --- a/src/script/hydra-eval-jobset +++ b/src/script/hydra-eval-jobset @@ -149,7 +149,7 @@ sub checkJobsetWrapped { my @args = ($jobset->nixexprinput, $jobset->nixexprpath, inputsToArgs($inputInfo, $exprType)); my $argsHash = sha256_hex("@args"); my $prevEval = getPrevJobsetEval($db, $jobset, 0); - if (defined $prevEval && $prevEval->hash eq $argsHash && !$dryRun) { + if (defined $prevEval && $prevEval->hash eq $argsHash && !$dryRun && !$jobset->forceeval) { print STDERR " jobset is unchanged, skipping\n"; Net::Statsd::increment("hydra.evaluator.unchanged_checkouts"); txn_do($db, sub { @@ -279,7 +279,7 @@ sub checkJobsetWrapped { # If this is a one-shot jobset, disable it now. $jobset->update({ enabled => 0 }) if $jobset->enabled == 2; - $jobset->update({ lastcheckedtime => time }); + $jobset->update({ lastcheckedtime => time, forceeval => undef }); }); my $dbStop = clock_gettime(CLOCK_REALTIME); diff --git a/src/sql/hydra.sql b/src/sql/hydra.sql index e1682759..f9f6fc73 100644 --- a/src/sql/hydra.sql +++ b/src/sql/hydra.sql @@ -68,6 +68,7 @@ create table Jobsets ( checkInterval integer not null default 300, -- minimum time in seconds between polls (0 = disable polling) schedulingShares integer not null default 100, fetchErrorMsg text, + forceEval boolean, check (schedulingShares > 0), primary key (project, name), foreign key (project) references Projects(name) on delete cascade on update cascade diff --git a/src/sql/upgrade-51.sql b/src/sql/upgrade-51.sql new file mode 100644 index 00000000..012763f1 --- /dev/null +++ b/src/sql/upgrade-51.sql @@ -0,0 +1 @@ +alter table Jobsets add column forceEval boolean;