Don't use isCurrent anymore; instead look up builds in the previous jobset evaluation. (The isCurrent field is still maintained because it's still used in some other places.)
To determine whether to perform an evaluation, compare the hash of the current inputs with the inputs of the previous jobset evaluation, rather than checking if there was ever an evaluation with those inputs. This way, if the inputs of an evaluation change back to a previous state, we get a new jobset evaluation in the database (and thus the latest jobset evaluation correctly represents the latest state of the jobset).
Improve performance by removing some unnecessary operations and adding an index.
RXVJFQ5AV3WME4HDVBPSRCALQTXROT4KQPOQVO6KTWTBNZIZZGPAC
L3UFM7DKGVPGIECPJ4IVJ77KG3LXZAY3PDDPOGJES6QFOTC2ZR6AC
R3ON2RJ3TKBYWR5YDELTKALWXHUQ6OJTNNOM3UOFACBN5W6DJVZAC
PIMGMGAFFP7UQFLLUZIY23G5DGJ5BQ52N3HX5NFKLUKZLHCDTQYQC
2WRTOU2Z2R3MWLRZCKK3ZZ2C5LJBH6GNJT77NETVA22Y23DUIX5QC
SM5M2J3AGBS4IHD7TBFBVNMXTUBVA5OIFIIJJDAU6KUCPRU4S74AC
KJQWSRCCQEKF64L4NYYZ7VKAF2YEPYXXTRW6BI464P6Q6KU34TQAC
3XTHEUMP2ZOMPQWE3S5QWHIHCEJNEXGDPQB3JUVZFPS3RFMY455QC
LBNVQXUBEZ45SOTGVXK5UEZXIAIZTJLWZNUYFI4JZ6J65N3KPDVQC
BMSQD2ZH3T37RNPRKKKNF5DTJEGBLY4YR2BZDKP7PXJGS3ZBBLWAC
OOQ2D3KCLFPYNAN253PHWLBQMB6OMO2KYQWQXLTP65SQAYZWQ5LAC
FM4O2L4MNPCHWRDRHKGKSH5TFFX6R2RMCPEQ3XCECA6UVLJPLUVQC
RFE6T5LGBFFNEPHZOPF4UNMFC2L4CGD5TPAMOXDLRPH3TZJ43UBAC
A22P7HCOGNO3XEQWBNEG2VHTGUB2GKQ75Q6JDMPQNQCLFHE7XBFAC
HPEG2RHVNHOPB5T4ZRXANIRBMVOVY3B5GFETJRYOTDJFVAYH2TQAC
MOX7XJ2E3XISXA7V7T4W6GEAGECGWBZ4PYSLTYBVVR4VAKOI33CQC
5SHCWE7XPQORSOLY7HGAIK2ODKBFPY4KVXRL2W7X6D4WALU544HQC
ZDENAYQI5DRRNUIDVKUGC45NK6C4ZFUL5FYMACTRZOCYQXPMY63QC
N22GPKYTOLZLBGTGDATQDVZ4R5APZEAOIA7L32X4UXBH4XNI7MWAC
S6OISBQ3HPFHAAQ5ENG7N3MNGOPNEJPIFKSSA5N4G6KJQTQBSSLQC
NI5BVF2VLMDA7REXTV455SUCQAYMKPKNKQSRII2SJJGG2TCX4CTAC
TIOBBINAK6IEDTCFBP67QDP3U7BHPVJOHBD6FEHASSSIQGNLCUXAC
S5PV6IIMKJ7PGWIFLLXERHYF3BCP2UEGFRZEZLD6UUBLVEZXJLUAC
SHZLOM5M2NVH2J7CJJMS562EV5NPCTNWQ5P3K2SSL2YFYUI7PMIQC
LZO3C2KIACZ3HN72RBGWWIT5ED4RJMYKI3SAHXT6RIUPHDFL3STQC
GCHNNFZPCYM3BPOCU5GASALJ6ONWMEVEEGVD7KKLTWC7YQKJ5KZAC
H7CNGK4OJNRYZQGPLBGR72DULLEPFQ5UISF5J24D7IMA7SYW5LGQC
4D4U5IPYZO2FONPOET4UP3ZPVPB35Q47SXU7A56G76V7VDFILOIAC
SQQSV4NBN6QB6BZVC7FCUFMWEKSGSNATQ3IFOVXJNTGSSGP4YM3QC
TULPZ62YXEHXUWGBZMLCLYILEXPQS5ADPT22574BIRFU4CZMBSKAC
D6YQQQCNJT7RJ4KF5JN76NM5HT4FVROBGSNB26LYPRYVLEG576MAC
T2232OBSNVDGHY46RY5BBB2IET5LV5OLKSSBDYUF7KAEDBUOTC7QC
6QRHXIM3XHCDLSIIBEGETDV67V6LTV55QMHC64ZPBMLTAECM5N3QC
C5W3WZ3YKLMDB7P6COIHDKSKSYDGAJBSIFIHFTEKRGSEJX7J7BNAC
34DPX2ORV3XDB7M3NYVZLU6MYDIFCIC5NHPJW7N5ITS356GWVMCAC
D5QIOJGPKQJIYBUCSC3MFJ3TXLPNZ2XMI37GXMFRVRFWWR2VMTFAC
}
# Return the most recent evaluation of the given jobset that had new
# builds, or undefined if no such evaluation exists.
sub getPrevJobsetEval {
my ($db, $jobset) = @_;
my ($prevEval) = $jobset->jobsetevals({ hasnewbuilds => 1 }, { order_by => "id DESC", rows => 1 });
return $prevEval;
my @previousBuilds = $job->builds->search({outPath => $outPath, isCurrent => 1});
if (scalar(@previousBuilds) > 0) {
print STDERR "already scheduled/built\n";
$currentBuilds->{$_->id} = 0 foreach @previousBuilds;
return;
if (defined $prevEval) {
my ($prevBuild) = $prevEval->builds->search({ job => $job->name, outPath => $outPath }, { rows => 1, columns => ['id'] });
if (defined $prevBuild) {
print STDERR " already scheduled/built as build ", $prevBuild->id, "\n";
$buildIds->{$prevBuild->id} = 0;
return;
}
my %extraFlags;
if (isValidPath($outPath)) {
%extraFlags =
( finished => 1
, iscachedbuild => 1
, buildstatus => 0
, starttime => $time
, stoptime => $time
, logfile => getBuildLog($drvPath)
, errormsg => ""
, releasename => getReleaseName($outPath)
);
} else {
%extraFlags = ( finished => 0 );
}
if (isValidPath($outPath)) {
print STDERR "marked as cached build ", $build->id, "\n";
$build->update(
{ finished => 1
, iscachedbuild => 1
, buildstatus => 0
, starttime => $time
, stoptime => $time
, logfile => getBuildLog($drvPath)
, errormsg => ""
, releasename => getReleaseName($outPath)
});
if ($build->iscachedbuild) {
print STDERR " marked as cached build ", $build->id, "\n";
print STDERR "added to queue as build ", $build->id, "\n";
$build->update(
{ priority => $priority
, busy => 0
, locker => ""
});
print STDERR " added to queue as build ", $build->id, "\n";
if (scalar($jobset->jobsetevals->search({hash => $argsHash})) > 0) {
print " already evaluated, skipping\n";
my $prevEval = getPrevJobsetEval($db, $jobset);
if ($prevEval->hash eq $argsHash) {
print STDERR " jobset is unchanged, skipping\n";
print "considering job " . $job->{jobName} . "\n";
checkBuild($db, $project, $jobset, $inputInfo, $nixExprInput, $job, \%currentBuilds);
print STDERR " considering job " . $project->name, ":", $jobset->name, ":", $job->{jobName} . "\n";
checkBuild($db, $project, $jobset, $inputInfo, $nixExprInput, $job, \%buildIds, $prevEval);
foreach my $job ($jobset->jobs->all) {
if ($failedJobNames{$job->name}) {
$job->update({errormsg => join '\n', @{$failedJobNames{$job->name}}});
} else {
$job->update({errormsg => undef});
}
}
$_->update({ errormsg => $failedJobNames{$_->name} ? join '\n', @{$failedJobNames{$_->name}} : undef })
foreach $jobset->jobs->all;
# Clear the "current" flag on all builds that are no longer
# current.
foreach my $build ($jobset->builds->search({iscurrent => 1})) {
$build->update({iscurrent => 0}) unless defined $currentBuilds{$build->id};
}
-- For hydra-update-gc-roots.
create index IndexBuildsOnKeep on Builds(keep);
create index IndexMostRecentSuccessfulBuilds on Builds(project, jobset, job, system, finished, buildStatus, id desc);
-- To get the most recent eval for a jobset.
create index IndexJobsetEvalsOnJobsetId on JobsetEvals(project, jobset, hasNewBuilds, id desc);
create index IndexJobsetEvalsOnJobsetId on JobsetEvals(project, jobset, hasNewBuilds, id desc);