Skip to content
Draft
94 changes: 50 additions & 44 deletions lib/Zonemaster/Backend/DB.pm
Original file line number Diff line number Diff line change
Expand Up @@ -60,46 +60,47 @@ The test is waiting to be processed.

=cut

Readonly our $TEST_WAITING => 'WAITING';
Readonly our $TEST_WAITING => 'waiting';

=head2 $TEST_RUNNING

The test is currently being processed.

=cut

Readonly our $TEST_RUNNING => 'RUNNING';
Readonly our $TEST_RUNNING => 'running';

=head2 $TEST_COMPLETED

The test was already processed.

This state encompasses all of the following:
=cut

=over 2
Readonly our $TEST_COMPLETED => 'completed';

=item
=head2 $TEST_CANCELLED

The Zonemaster Engine test terminated normally.
The test was cancelled.

=item
=cut

A critical error occurred while processing.
Readonly our $TEST_CANCELLED => 'cancelled';

=item
=head2 $TEST_CRASHED

The processing was cancelled because it took too long.

=back
The test crashed.

=cut

Readonly our $TEST_COMPLETED => 'COMPLETED';
Readonly our $TEST_CRASHED => 'crashed';


our @EXPORT_OK = qw(
$TEST_WAITING
$TEST_RUNNING
$TEST_COMPLETED
$TEST_CANCELLED
$TEST_CRASHED
);


Expand Down Expand Up @@ -217,18 +218,20 @@ sub create_new_test {
created_at,
priority,
queue,
state,
fingerprint,
params,
domain,
undelegated
) VALUES (?,?,?,?,?,?,?,?,?)
) VALUES (?,?,?,?,?,?,?,?,?,?)
],
undef,
$hash_id,
$batch_id,
$self->format_time( time() ),
$priority,
$queue_label,
$TEST_WAITING,
$fingerprint,
$encoded_params,
encode_utf8( $test_params->{domain} ),
Expand Down Expand Up @@ -312,12 +315,13 @@ sub test_progress {
UPDATE test_results
SET progress = ?
WHERE hash_id = ?
AND 1 <= progress
AND state = ?
AND progress <= ?
],
undef,
$progress,
$test_id,
$TEST_RUNNING,
$progress,
);
if ( $rows_affected == 0 ) {
Expand Down Expand Up @@ -346,35 +350,27 @@ sub test_progress {
sub test_state {
my ( $self, $test_id ) = @_;

my ( $progress ) = $self->dbh->selectrow_array(
my ( $state ) = $self->dbh->selectrow_array(
q[
SELECT progress
SELECT state
FROM test_results
WHERE hash_id = ?
],
undef,
$test_id,
);
if ( !defined $progress ) {

if ( !defined $state ) {
die Zonemaster::Backend::Error::Internal->new( reason => 'job not found' );
}

if ( $progress == 0 ) {
return $TEST_WAITING;
}
elsif ( 0 < $progress && $progress < 100 ) {
return $TEST_RUNNING;
}
elsif ( $progress == 100 ) {
return $TEST_COMPLETED;
}
else {
die Zonemaster::Backend::Error::Internal->new( reason => 'state could not be determined' );
}
return $state;
}

sub set_test_completed {
my ( $self, $test_id ) = @_;
my ( $self, $test_id, $state) = @_;

$state //= $TEST_COMPLETED;

my $current_state = $self->test_state( $test_id );

Expand All @@ -386,12 +382,14 @@ sub set_test_completed {
q[
UPDATE test_results
SET progress = 100,
state = ?,
ended_at = ?
WHERE hash_id = ?
AND 0 < progress
AND progress < 100
],
undef,
$state,
$self->format_time( time() ),
$test_id,
);
Expand Down Expand Up @@ -436,16 +434,18 @@ sub store_results {
q[
UPDATE test_results
SET progress = 100,
state = ?,
ended_at = ?,
results = ?
WHERE hash_id = ?
AND 0 < progress
AND progress < 100
AND state = ?
],
undef,
$TEST_COMPLETED,
$self->format_time( time() ),
$new_results,
$test_id,
$TEST_RUNNING,
);

if ( $rows_affected == 0 ) {
Expand Down Expand Up @@ -641,13 +641,14 @@ sub get_test_request {
SELECT hash_id,
batch_id
FROM test_results
WHERE progress = 0
WHERE state = ?
AND queue = ?
ORDER BY priority DESC,
id ASC
LIMIT 1
],
undef,
$TEST_WAITING,
$queue_label,
);
}
Expand All @@ -657,11 +658,13 @@ sub get_test_request {
SELECT hash_id,
batch_id
FROM test_results
WHERE progress = 0
WHERE state = ?
ORDER BY priority DESC,
id ASC
LIMIT 1
],
undef,
$TEST_WAITING,
);
}

Expand Down Expand Up @@ -700,13 +703,16 @@ sub claim_test {
q[
UPDATE test_results
SET progress = 1,
state = ?,
started_at = ?
WHERE hash_id = ?
AND progress = 0
AND state = ?
],
undef,
$TEST_RUNNING,
$self->format_time( time() ),
$test_id,
$TEST_WAITING,
);

return $rows_affected == 1;
Expand Down Expand Up @@ -813,7 +819,7 @@ sub process_unfinished_tests {
}
);
while ( my $h = $sth1->fetchrow_hashref ) {
$self->force_end_test($h->{hash_id}, $msg);
$self->force_end_test($h->{hash_id}, $msg, $TEST_CANCELLED);
}
}

Expand All @@ -832,11 +838,11 @@ sub select_unfinished_tests {
SELECT hash_id, results
FROM test_results
WHERE started_at < ?
AND progress > 0
AND progress < 100
AND state = ?
AND queue = ?" );
$sth->execute( #
$self->format_time( time() - $test_run_timeout ),
$TEST_RUNNING,
$queue_label,
);
return $sth;
Expand All @@ -846,10 +852,10 @@ sub select_unfinished_tests {
SELECT hash_id, results
FROM test_results
WHERE started_at < ?
AND progress > 0
AND progress < 100" );
AND state = ?" );
$sth->execute( #
$self->format_time( time() - $test_run_timeout ),
$TEST_RUNNING,
);
return $sth;
}
Expand All @@ -863,10 +869,10 @@ and mark test with $hash_id as COMPLETED.
=cut

sub force_end_test {
my ( $self, $hash_id, $msg ) = @_;
my ( $self, $hash_id, $msg ,$state) = @_;

$self->add_result_entries( $hash_id, $msg );
$self->set_test_completed( $hash_id );
$self->set_test_completed( $hash_id, $state);
}

=head2 process_dead_test($hash_id)
Expand All @@ -888,7 +894,7 @@ sub process_dead_test {
timestamp => $self->get_relative_start_time($hash_id)
}
);
$self->force_end_test($hash_id, $msg);
$self->force_end_test($hash_id, $msg, $TEST_CRASHED);
}

# Converts the domain to lowercase and if the domain is not the root ('.')
Expand Down
4 changes: 3 additions & 1 deletion lib/Zonemaster/Backend/DB/MySQL.pm
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ sub create_schema {
priority integer DEFAULT 10,
queue integer DEFAULT 0,
progress integer DEFAULT 0,
state VARCHAR(20) NOT NULL DEFAULT "waiting",
fingerprint character varying(32),
params blob NOT NULL,
results mediumblob DEFAULT NULL,
undelegated integer NOT NULL DEFAULT 0,

UNIQUE (hash_id)
UNIQUE (hash_id),
CHECK (state IN ("waiting", "running", "completed", "cancelled", "crashed"))
) ENGINE=InnoDB
'
) or die Zonemaster::Backend::Error::Internal->new( reason => "MySQL error, could not create 'test_results' table", data => $dbh->errstr() );
Expand Down
4 changes: 3 additions & 1 deletion lib/Zonemaster/Backend/DB/PostgreSQL.pm
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@ sub create_schema {
priority integer DEFAULT 10,
queue integer DEFAULT 0,
progress integer DEFAULT 0,
state VARCHAR(20) NOT NULL DEFAULT "waiting",
fingerprint varchar(32),
params json NOT NULL,
undelegated integer NOT NULL DEFAULT 0,
results json,

UNIQUE (hash_id)
UNIQUE (hash_id),
CHECK (state IN ("waiting", "running", "completed", "cancelled", "crashed"))
)
'
) or die Zonemaster::Backend::Error::Internal->new( reason => "PostgreSQL error, could not create 'test_results' table", data => $dbh->errstr() );
Expand Down
4 changes: 3 additions & 1 deletion lib/Zonemaster/Backend/DB/SQLite.pm
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ sub create_schema {
priority integer DEFAULT 10,
queue integer DEFAULT 0,
progress integer DEFAULT 0,
state VARCHAR(20) NOT NULL DEFAULT "waiting",
fingerprint character varying(32),
params text NOT NULL,
results text DEFAULT NULL,
undelegated boolean NOT NULL DEFAULT false,

UNIQUE (hash_id)
UNIQUE (hash_id),
CHECK (state IN ("waiting", "running", "completed", "cancelled", "crashed"))
)
'
) or die Zonemaster::Backend::Error::Internal->new( reason => "SQLite error, could not create 'test_results' table", data => $dbh->errstr() );
Expand Down
Loading