Remove Hydra::Helper::nix::txn_do from the Perl code

To quote the function's comment:

  Awful hack to handle timeouts in SQLite: just retry the transaction.
  DBD::SQLite *has* a 30 second retry window, but apparently it
  doesn't work.

Since SQLite is now dropped entirely, this wrapper can be removed
completely.
This commit is contained in:
Maximilian Bosch 2020-04-10 18:13:36 +02:00
parent efcbc08686
commit 721c764951
No known key found for this signature in database
GPG key ID: 091DBF4D1FC46B8E
18 changed files with 34 additions and 50 deletions

View file

@ -214,7 +214,7 @@ sub scmdiff : Path('/api/scmdiff') Args(0) {
sub triggerJobset { sub triggerJobset {
my ($self, $c, $jobset, $force) = @_; my ($self, $c, $jobset, $force) = @_;
print STDERR "triggering jobset ", $jobset->get_column('project') . ":" . $jobset->name, "\n"; print STDERR "triggering jobset ", $jobset->get_column('project') . ":" . $jobset->name, "\n";
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
$jobset->update({ triggertime => time }); $jobset->update({ triggertime => time });
$jobset->update({ forceeval => 1 }) if $force; $jobset->update({ forceeval => 1 }) if $force;
}); });

View file

@ -90,7 +90,7 @@ sub news_submit : Chained('admin') PathPart('news/submit') Args(0) {
sub news_delete : Chained('admin') PathPart('news/delete') Args(1) { sub news_delete : Chained('admin') PathPart('news/delete') Args(1) {
my ($self, $c, $id) = @_; my ($self, $c, $id) = @_;
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
my $newsItem = $c->model('DB::NewsItems')->find($id) my $newsItem = $c->model('DB::NewsItems')->find($id)
or notFound($c, "Newsitem with id $id doesn't exist."); or notFound($c, "Newsitem with id $id doesn't exist.");
$newsItem->delete; $newsItem->delete;

View file

@ -526,7 +526,7 @@ sub keep : Chained('buildChain') PathPart Args(1) {
registerRoot $_->path foreach $build->buildoutputs; registerRoot $_->path foreach $build->buildoutputs;
} }
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
$build->update({keep => $keep}); $build->update({keep => $keep});
}); });

View file

@ -62,7 +62,7 @@ sub jobset_PUT {
} }
if (defined $c->stash->{jobset}) { if (defined $c->stash->{jobset}) {
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
updateJobset($c, $c->stash->{jobset}); updateJobset($c, $c->stash->{jobset});
}); });
@ -74,7 +74,7 @@ sub jobset_PUT {
else { else {
my $jobset; my $jobset;
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
# Note: $jobsetName is validated in updateProject, which will # Note: $jobsetName is validated in updateProject, which will
# abort the transaction if the name isn't valid. # abort the transaction if the name isn't valid.
$jobset = $c->stash->{project}->jobsets->create( $jobset = $c->stash->{project}->jobsets->create(
@ -100,7 +100,7 @@ sub jobset_DELETE {
error($c, "can't modify jobset of declarative project", 403); error($c, "can't modify jobset of declarative project", 403);
} }
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
$c->stash->{jobset}->jobsetevals->delete; $c->stash->{jobset}->jobsetevals->delete;
$c->stash->{jobset}->builds->delete; $c->stash->{jobset}->builds->delete;
$c->stash->{jobset}->delete; $c->stash->{jobset}->delete;

View file

@ -146,7 +146,7 @@ sub release : Chained('evalChain') PathPart('release') Args(0) {
my $release; my $release;
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
$release = $c->stash->{project}->releases->create( $release = $c->stash->{project}->releases->create(
{ name => $releaseName { name => $releaseName

View file

@ -41,7 +41,7 @@ sub project_PUT {
if (defined $c->stash->{project}) { if (defined $c->stash->{project}) {
requireProjectOwner($c, $c->stash->{project}); requireProjectOwner($c, $c->stash->{project});
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
updateProject($c, $c->stash->{project}); updateProject($c, $c->stash->{project});
}); });
@ -55,7 +55,7 @@ sub project_PUT {
requireMayCreateProjects($c); requireMayCreateProjects($c);
my $project; my $project;
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
# Note: $projectName is validated in updateProject, # Note: $projectName is validated in updateProject,
# which will abort the transaction if the name isn't # which will abort the transaction if the name isn't
# valid. Idem for the owner. # valid. Idem for the owner.
@ -77,7 +77,7 @@ sub project_DELETE {
requireProjectOwner($c, $c->stash->{project}); requireProjectOwner($c, $c->stash->{project});
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
$c->stash->{project}->jobsetevals->delete; $c->stash->{project}->jobsetevals->delete;
$c->stash->{project}->builds->delete; $c->stash->{project}->builds->delete;
$c->stash->{project}->delete; $c->stash->{project}->delete;
@ -198,7 +198,7 @@ sub create_release_submit : Chained('projectChain') PathPart('create-release/sub
my $releaseName = $c->request->params->{name}; my $releaseName = $c->request->params->{name};
my $release; my $release;
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
# Note: $releaseName is validated in updateRelease, which will # Note: $releaseName is validated in updateRelease, which will
# abort the transaction if the name isn't valid. # abort the transaction if the name isn't valid.
$release = $c->stash->{project}->releases->create( $release = $c->stash->{project}->releases->create(

View file

@ -63,13 +63,13 @@ sub submit : Chained('release') PathPart('submit') Args(0) {
requireProjectOwner($c, $c->stash->{project}); requireProjectOwner($c, $c->stash->{project});
if (($c->request->params->{action} || "") eq "delete") { if (($c->request->params->{action} || "") eq "delete") {
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
$c->stash->{release}->delete; $c->stash->{release}->delete;
}); });
$c->res->redirect($c->uri_for($c->controller('Project')->action_for('project'), $c->res->redirect($c->uri_for($c->controller('Project')->action_for('project'),
[$c->stash->{project}->name])); [$c->stash->{project}->name]));
} else { } else {
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
updateRelease($c, $c->stash->{release}); updateRelease($c, $c->stash->{release});
}); });
$c->res->redirect($c->uri_for($self->action_for("view"), $c->res->redirect($c->uri_for($self->action_for("view"),

View file

@ -163,7 +163,7 @@ sub register :Local Args(0) {
error($c, "Your user name is already taken.") error($c, "Your user name is already taken.")
if $c->find_user({ username => $userName }); if $c->find_user({ username => $userName });
txn_do($c->model('DB')->schema, sub { $c->model('DB')->schema->txn_do(sub {
my $user = $c->model('DB::Users')->create( my $user = $c->model('DB::Users')->create(
{ username => $userName { username => $userName
, password => "!" , password => "!"
@ -261,7 +261,7 @@ sub edit_PUT {
return; return;
} }
txn_do($c->model('DB')->schema, sub { $c->model('Db')->schema->txn_do(sub {
updatePreferences($c, $user); updatePreferences($c, $user);
}); });

View file

@ -46,7 +46,7 @@ sub updateDeclarativeJobset {
$update{$key} = $declSpec->{$key}; $update{$key} = $declSpec->{$key};
delete $declSpec->{$key}; delete $declSpec->{$key};
} }
txn_do($db, sub { $db->txn_do(sub {
my $jobset = $project->jobsets->update_or_create(\%update); my $jobset = $project->jobsets->update_or_create(\%update);
$jobset->jobsetinputs->delete; $jobset->jobsetinputs->delete;
while ((my $name, my $data) = each %{$declSpec->{"inputs"}}) { while ((my $name, my $data) = each %{$declSpec->{"inputs"}}) {
@ -79,7 +79,7 @@ sub handleDeclarativeJobsetBuild {
} }
my $declSpec = decode_json($declText); my $declSpec = decode_json($declText);
txn_do($db, sub { $db->txn_do(sub {
my @kept = keys %$declSpec; my @kept = keys %$declSpec;
push @kept, ".jobsets"; push @kept, ".jobsets";
$project->jobsets->search({ name => { "not in" => \@kept } })->update({ enabled => 0, hidden => 1 }); $project->jobsets->search({ name => { "not in" => \@kept } })->update({ enabled => 0, hidden => 1 });

View file

@ -14,7 +14,7 @@ use IPC::Run;
our @ISA = qw(Exporter); our @ISA = qw(Exporter);
our @EXPORT = qw( our @EXPORT = qw(
getHydraHome getHydraConfig getBaseUrl txn_do getHydraHome getHydraConfig getBaseUrl
getSCMCacheDir getSCMCacheDir
registerRoot getGCRootsDir gcRootFor registerRoot getGCRootsDir gcRootFor
jobsetOverview jobsetOverview_ jobsetOverview jobsetOverview_
@ -61,22 +61,6 @@ sub getBaseUrl {
} }
# Awful hack to handle timeouts in SQLite: just retry the transaction.
# DBD::SQLite *has* a 30 second retry window, but apparently it
# doesn't work.
sub txn_do {
my ($db, $coderef) = @_;
my $res;
while (1) {
eval {
$res = $db->txn_do($coderef);
};
return $res if !$@;
die $@ unless $@ =~ "database is locked";
}
}
sub getSCMCacheDir { sub getSCMCacheDir {
return Hydra::Model::DB::getHydraPath . "/scm" ; return Hydra::Model::DB::getHydraPath . "/scm" ;
} }
@ -446,7 +430,7 @@ sub getTotalShares {
sub cancelBuilds($$) { sub cancelBuilds($$) {
my ($db, $builds) = @_; my ($db, $builds) = @_;
return txn_do($db, sub { return $db->txn_do(sub {
$builds = $builds->search({ finished => 0 }); $builds = $builds->search({ finished => 0 });
my $n = $builds->count; my $n = $builds->count;
my $time = time(); my $time = time();
@ -473,7 +457,7 @@ sub restartBuilds($$) {
my $nrRestarted = 0; my $nrRestarted = 0;
txn_do($db, sub { $db->txn_do(sub {
# Reset the stats for the evals to which the builds belongs. # Reset the stats for the evals to which the builds belongs.
# !!! Should do this in a trigger. # !!! Should do this in a trigger.
$db->resultset('JobsetEvals')->search( $db->resultset('JobsetEvals')->search(

View file

@ -58,7 +58,7 @@ sub fetchInput {
# FIXME: time window between nix-prefetch-bzr and addTempRoot. # FIXME: time window between nix-prefetch-bzr and addTempRoot.
addTempRoot($storePath); addTempRoot($storePath);
txn_do($self->{db}, sub { $self->{db}->txn_do(sub {
$self->{db}->resultset('CachedBazaarInputs')->create( $self->{db}->resultset('CachedBazaarInputs')->create(
{ uri => $uri { uri => $uri
, revision => $revision , revision => $revision

View file

@ -77,7 +77,7 @@ sub fetchInput {
$sha256 = queryPathHash($storePath); $sha256 = queryPathHash($storePath);
$sha256 =~ s/sha256://; $sha256 =~ s/sha256://;
txn_do($self->{db}, sub { $self->{db}->txn_do(sub {
$self->{db}->resultset('CachedDarcsInputs')->update_or_create( $self->{db}->resultset('CachedDarcsInputs')->update_or_create(
{ uri => $uri { uri => $uri
, revision => $revision , revision => $revision

View file

@ -218,7 +218,7 @@ sub fetchInput {
# FIXME: time window between nix-prefetch-git and addTempRoot. # FIXME: time window between nix-prefetch-git and addTempRoot.
addTempRoot($storePath); addTempRoot($storePath);
txn_do($self->{db}, sub { $self->{db}->txn_do(sub {
$self->{db}->resultset('CachedGitInputs')->update_or_create( $self->{db}->resultset('CachedGitInputs')->update_or_create(
{ uri => $uri { uri => $uri
, branch => $branch , branch => $branch

View file

@ -85,7 +85,7 @@ sub fetchInput {
# FIXME: time window between nix-prefetch-hg and addTempRoot. # FIXME: time window between nix-prefetch-hg and addTempRoot.
addTempRoot($storePath); addTempRoot($storePath);
txn_do($self->{db}, sub { $self->{db}->txn_do(sub {
$self->{db}->resultset('CachedHgInputs')->update_or_create( $self->{db}->resultset('CachedHgInputs')->update_or_create(
{ uri => $uri { uri => $uri
, branch => $branch , branch => $branch

View file

@ -54,7 +54,7 @@ sub fetchInput {
# changes, we get a new "revision", but if it doesn't change # changes, we get a new "revision", but if it doesn't change
# (or changes back), we don't get a new "revision". # (or changes back), we don't get a new "revision".
if (!defined $cachedInput) { if (!defined $cachedInput) {
txn_do($self->{db}, sub { $self->{db}->txn_do(sub {
$self->{db}->resultset('CachedPathInputs')->update_or_create( $self->{db}->resultset('CachedPathInputs')->update_or_create(
{ srcpath => $uri { srcpath => $uri
, timestamp => $timestamp , timestamp => $timestamp
@ -65,7 +65,7 @@ sub fetchInput {
}); });
} else { } else {
$timestamp = $cachedInput->timestamp; $timestamp = $cachedInput->timestamp;
txn_do($self->{db}, sub { $self->{db}->txn_do(sub {
$cachedInput->update({lastseen => time}); $cachedInput->update({lastseen => time});
}); });
} }

View file

@ -71,7 +71,7 @@ sub fetchInput {
$sha256 = queryPathHash($storePath); $sha256 =~ s/sha256://; $sha256 = queryPathHash($storePath); $sha256 =~ s/sha256://;
txn_do($self->{db}, sub { $self->{db}->txn_do(sub {
$self->{db}->resultset('CachedSubversionInputs')->update_or_create( $self->{db}->resultset('CachedSubversionInputs')->update_or_create(
{ uri => $uri { uri => $uri
, revision => $revision , revision => $revision

View file

@ -54,7 +54,7 @@ die "$0: type must be `hydra' or `google'\n"
my $db = Hydra::Model::DB->new(); my $db = Hydra::Model::DB->new();
txn_do($db, sub { $db->txn_do(sub {
my $user = $db->resultset('Users')->find({ username => $renameFrom // $userName }); my $user = $db->resultset('Users')->find({ username => $renameFrom // $userName });
if ($renameFrom) { if ($renameFrom) {
die "$0: user `$renameFrom' does not exist\n" unless $user; die "$0: user `$renameFrom' does not exist\n" unless $user;

View file

@ -399,7 +399,7 @@ sub checkBuild {
my $build; my $build;
txn_do($db, sub { $db->txn_do(sub {
my $job = $jobset->jobs->update_or_create({ my $job = $jobset->jobs->update_or_create({
name => $jobName, name => $jobName,
jobset_id => $jobset->id, jobset_id => $jobset->id,
@ -501,7 +501,7 @@ sub setJobsetError {
my $prevError = $jobset->errormsg; my $prevError = $jobset->errormsg;
eval { eval {
txn_do($db, sub { $db->txn_do(sub {
$jobset->update({ errormsg => $errorMsg, errortime => time, fetcherrormsg => undef }); $jobset->update({ errormsg => $errorMsg, errortime => time, fetcherrormsg => undef });
}); });
}; };
@ -603,7 +603,7 @@ sub checkJobsetWrapped {
if ($fetchError) { if ($fetchError) {
Net::Statsd::increment("hydra.evaluator.failed_checkouts"); Net::Statsd::increment("hydra.evaluator.failed_checkouts");
print STDERR $fetchError; print STDERR $fetchError;
txn_do($db, sub { $db->txn_do(sub {
$jobset->update({ lastcheckedtime => time, fetcherrormsg => $fetchError }) if !$dryRun; $jobset->update({ lastcheckedtime => time, fetcherrormsg => $fetchError }) if !$dryRun;
$db->storage->dbh->do("notify eval_failed, ?", undef, join('\t', $tmpId)); $db->storage->dbh->do("notify eval_failed, ?", undef, join('\t', $tmpId));
}); });
@ -619,7 +619,7 @@ sub checkJobsetWrapped {
if (defined $prevEval && $prevEval->hash eq $argsHash && !$dryRun && !$jobset->forceeval && $prevEval->flake eq $flakeRef) { if (defined $prevEval && $prevEval->hash eq $argsHash && !$dryRun && !$jobset->forceeval && $prevEval->flake eq $flakeRef) {
print STDERR " jobset is unchanged, skipping\n"; print STDERR " jobset is unchanged, skipping\n";
Net::Statsd::increment("hydra.evaluator.unchanged_checkouts"); Net::Statsd::increment("hydra.evaluator.unchanged_checkouts");
txn_do($db, sub { $db->txn_do(sub {
$jobset->update({ lastcheckedtime => time, fetcherrormsg => undef }); $jobset->update({ lastcheckedtime => time, fetcherrormsg => undef });
$db->storage->dbh->do("notify eval_cached, ?", undef, join('\t', $tmpId)); $db->storage->dbh->do("notify eval_cached, ?", undef, join('\t', $tmpId));
}); });
@ -660,7 +660,7 @@ sub checkJobsetWrapped {
my $dbStart = clock_gettime(CLOCK_MONOTONIC); my $dbStart = clock_gettime(CLOCK_MONOTONIC);
my %buildMap; my %buildMap;
txn_do($db, sub { $db->txn_do(sub {
my $prevEval = getPrevJobsetEval($db, $jobset, 1); my $prevEval = getPrevJobsetEval($db, $jobset, 1);
@ -806,7 +806,7 @@ sub checkJobset {
my $failed = 0; my $failed = 0;
if ($checkError) { if ($checkError) {
print STDERR $checkError; print STDERR $checkError;
txn_do($db, sub { $db->txn_do(sub {
$jobset->update({lastcheckedtime => time}); $jobset->update({lastcheckedtime => time});
setJobsetError($jobset, $checkError); setJobsetError($jobset, $checkError);
$db->storage->dbh->do("notify eval_failed, ?", undef, join('\t', $tmpId)); $db->storage->dbh->do("notify eval_failed, ?", undef, join('\t', $tmpId));