forked from lix-project/hydra
Materialize the number of finished builds
The NrBuilds table tracks the value of ‘select count(*) from Builds where finished = 0’, keeping it up to date via a trigger. This is necessary to make the /all page fast, since otherwise it needs to do a sequential scan on the Builds table.
This commit is contained in:
parent
182f725612
commit
452c8e36d1
|
@ -56,13 +56,12 @@ sub all : Chained('get_builds') PathPart {
|
||||||
|
|
||||||
my $resultsPerPage = 20;
|
my $resultsPerPage = 20;
|
||||||
|
|
||||||
my $nrBuilds = $c->stash->{allBuilds}->search({finished => 1})->count;
|
|
||||||
|
|
||||||
$c->stash->{baseUri} = $c->uri_for($self->action_for("all"), $c->req->captures);
|
$c->stash->{baseUri} = $c->uri_for($self->action_for("all"), $c->req->captures);
|
||||||
|
|
||||||
$c->stash->{page} = $page;
|
$c->stash->{page} = $page;
|
||||||
$c->stash->{resultsPerPage} = $resultsPerPage;
|
$c->stash->{resultsPerPage} = $resultsPerPage;
|
||||||
$c->stash->{total} = $nrBuilds;
|
$c->stash->{total} = $c->stash->{allBuilds}->search({finished => 1})->count
|
||||||
|
unless defined $c->stash->{total};
|
||||||
|
|
||||||
$c->stash->{builds} = [ $c->stash->{allBuilds}->search(
|
$c->stash->{builds} = [ $c->stash->{allBuilds}->search(
|
||||||
{ finished => 1 },
|
{ finished => 1 },
|
||||||
|
|
|
@ -155,6 +155,7 @@ sub get_builds : Chained('/') PathPart('') CaptureArgs(0) {
|
||||||
$c->stash->{allJobs} = $c->model('DB::Jobs');
|
$c->stash->{allJobs} = $c->model('DB::Jobs');
|
||||||
$c->stash->{latestSucceeded} = $c->model('DB')->resultset('LatestSucceeded');
|
$c->stash->{latestSucceeded} = $c->model('DB')->resultset('LatestSucceeded');
|
||||||
$c->stash->{channelBaseName} = "everything";
|
$c->stash->{channelBaseName} = "everything";
|
||||||
|
$c->stash->{total} = $c->model('DB::NrBuilds')->find('finished')->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
75
src/lib/Hydra/Schema/NrBuilds.pm
Normal file
75
src/lib/Hydra/Schema/NrBuilds.pm
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
use utf8;
|
||||||
|
package Hydra::Schema::NrBuilds;
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader
|
||||||
|
# DO NOT MODIFY THE FIRST PART OF THIS FILE
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Hydra::Schema::NrBuilds
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use base 'DBIx::Class::Core';
|
||||||
|
|
||||||
|
=head1 COMPONENTS LOADED
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item * L<Hydra::Component::ToJSON>
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
__PACKAGE__->load_components("+Hydra::Component::ToJSON");
|
||||||
|
|
||||||
|
=head1 TABLE: C<NrBuilds>
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
__PACKAGE__->table("NrBuilds");
|
||||||
|
|
||||||
|
=head1 ACCESSORS
|
||||||
|
|
||||||
|
=head2 what
|
||||||
|
|
||||||
|
data_type: 'text'
|
||||||
|
is_nullable: 0
|
||||||
|
|
||||||
|
=head2 count
|
||||||
|
|
||||||
|
data_type: 'integer'
|
||||||
|
is_nullable: 0
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
__PACKAGE__->add_columns(
|
||||||
|
"what",
|
||||||
|
{ data_type => "text", is_nullable => 0 },
|
||||||
|
"count",
|
||||||
|
{ data_type => "integer", is_nullable => 0 },
|
||||||
|
);
|
||||||
|
|
||||||
|
=head1 PRIMARY KEY
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item * L</what>
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
__PACKAGE__->set_primary_key("what");
|
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-08-12 17:59:18
|
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CK8eJGC803nGj0wnete9xg
|
||||||
|
|
||||||
|
|
||||||
|
# You can replace this text with custom code or comments, and it will be preserved on regeneration
|
||||||
|
1;
|
|
@ -51,12 +51,12 @@ for (my $n = $schemaVersion; $n < $maxSchemaVersion; $n++) {
|
||||||
my @statements = $sql_splitter->split($schema);
|
my @statements = $sql_splitter->split($schema);
|
||||||
eval {
|
eval {
|
||||||
$dbh->begin_work;
|
$dbh->begin_work;
|
||||||
sub run {
|
sub run_ {
|
||||||
my ($stm) = @_;
|
my ($stm) = @_;
|
||||||
print STDERR "executing SQL statement: $stm\n";
|
print STDERR "executing SQL statement: $stm\n";
|
||||||
$dbh->do($_);
|
$dbh->do($_);
|
||||||
}
|
}
|
||||||
run($_) foreach @statements;
|
run_($_) foreach @statements;
|
||||||
$db->resultset('SchemaVersion')->update({version => $m});
|
$db->resultset('SchemaVersion')->update({version => $m});
|
||||||
$dbh->commit;
|
$dbh->commit;
|
||||||
};
|
};
|
||||||
|
|
|
@ -514,6 +514,36 @@ create table NewsItems (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
-- Cache of the number of finished builds.
|
||||||
|
create table NrBuilds (
|
||||||
|
what text primary key not null,
|
||||||
|
count integer not null
|
||||||
|
);
|
||||||
|
|
||||||
|
insert into NrBuilds(what, count) values('finished', 0);
|
||||||
|
|
||||||
|
#ifdef POSTGRESQL
|
||||||
|
|
||||||
|
create function modifyNrBuildsFinished() returns trigger as $$
|
||||||
|
begin
|
||||||
|
if ((tg_op = 'INSERT' and new.finished = 1) or
|
||||||
|
(tg_op = 'UPDATE' and old.finished = 0 and new.finished = 1)) then
|
||||||
|
update NrBuilds set count = count + 1 where what = 'finished';
|
||||||
|
elsif ((tg_op = 'DELETE' and old.finished = 1) or
|
||||||
|
(tg_op = 'UPDATE' and old.finished = 1 and new.finished = 0)) then
|
||||||
|
update NrBuilds set count = count - 1 where what = 'finished';
|
||||||
|
end if;
|
||||||
|
return null;
|
||||||
|
end;
|
||||||
|
$$ language plpgsql;
|
||||||
|
|
||||||
|
create trigger NrBuildsFinished after insert or update or delete on Builds
|
||||||
|
for each row
|
||||||
|
execute procedure modifyNrBuildsFinished();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
-- Some indices.
|
-- Some indices.
|
||||||
|
|
||||||
create index IndexBuildInputsOnBuild on BuildInputs(build);
|
create index IndexBuildInputsOnBuild on BuildInputs(build);
|
||||||
|
@ -534,7 +564,7 @@ create index IndexBuildsOnJobAndSystem on Builds(project, jobset, job, system);
|
||||||
create index IndexBuildsOnJobset on Builds(project, jobset);
|
create index IndexBuildsOnJobset on Builds(project, jobset);
|
||||||
create index IndexBuildsOnProject on Builds(project);
|
create index IndexBuildsOnProject on Builds(project);
|
||||||
create index IndexBuildsOnTimestamp on Builds(timestamp);
|
create index IndexBuildsOnTimestamp on Builds(timestamp);
|
||||||
create index IndexBuildsOnJobsetFinishedTimestamp on Builds(project, jobset, finished, timestamp DESC);
|
create index IndexBuildsOnJobsetFinishedTimestamp on Builds(project, jobset, finished, timestamp DESC); -- obsolete?
|
||||||
create index IndexBuildsOnJobFinishedId on builds(project, jobset, job, system, finished, id DESC);
|
create index IndexBuildsOnJobFinishedId on builds(project, jobset, job, system, finished, id DESC);
|
||||||
create index IndexBuildsOnJobSystemCurrent on Builds(project, jobset, job, system, isCurrent);
|
create index IndexBuildsOnJobSystemCurrent on Builds(project, jobset, job, system, isCurrent);
|
||||||
create index IndexBuildsOnDrvPath on Builds(drvPath);
|
create index IndexBuildsOnDrvPath on Builds(drvPath);
|
||||||
|
|
23
src/sql/upgrade-17.sql
Normal file
23
src/sql/upgrade-17.sql
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
create table NrBuilds (
|
||||||
|
what text primary key not null,
|
||||||
|
count integer not null
|
||||||
|
);
|
||||||
|
|
||||||
|
create function modifyNrBuildsFinished() returns trigger as $$
|
||||||
|
begin
|
||||||
|
if ((tg_op = 'INSERT' and new.finished = 1) or
|
||||||
|
(tg_op = 'UPDATE' and old.finished = 0 and new.finished = 1)) then
|
||||||
|
update NrBuilds set count = count + 1 where what = 'finished';
|
||||||
|
elsif ((tg_op = 'DELETE' and old.finished = 1) or
|
||||||
|
(tg_op = 'UPDATE' and old.finished = 1 and new.finished = 0)) then
|
||||||
|
update NrBuilds set count = count - 1 where what = 'finished';
|
||||||
|
end if;
|
||||||
|
return null;
|
||||||
|
end;
|
||||||
|
$$ language plpgsql;
|
||||||
|
|
||||||
|
create trigger NrBuildsFinished after insert or update or delete on Builds
|
||||||
|
for each row
|
||||||
|
execute procedure modifyNrBuildsFinished();
|
||||||
|
|
||||||
|
insert into NrBuilds(what, count) select 'finished', count(*) from Builds where finished = 1;
|
|
@ -7,11 +7,11 @@ my $db = Hydra::Model::DB->new;
|
||||||
my @sources = $db->schema->sources;
|
my @sources = $db->schema->sources;
|
||||||
my $nrtables = scalar(@sources);
|
my $nrtables = scalar(@sources);
|
||||||
|
|
||||||
use Test::Simple tests => 43;
|
use Test::Simple tests => 44;
|
||||||
|
|
||||||
foreach my $source (@sources) {
|
foreach my $source (@sources) {
|
||||||
my $title = "Basic select query for $source";
|
my $title = "Basic select query for $source";
|
||||||
if ($source eq "SchemaVersion") {
|
if ($source eq "SchemaVersion" || $source eq "NrBuilds") {
|
||||||
ok(scalar($db->resultset($source)->all) == 1, $title);
|
ok(scalar($db->resultset($source)->all) == 1, $title);
|
||||||
} elsif( $source !~ m/^(LatestSucceeded|JobStatus|ActiveJobs)/) {
|
} elsif( $source !~ m/^(LatestSucceeded|JobStatus|ActiveJobs)/) {
|
||||||
ok(scalar($db->resultset($source)->all) == 0, $title);
|
ok(scalar($db->resultset($source)->all) == 0, $title);
|
||||||
|
|
Loading…
Reference in a new issue