Skip to content

Commit 76b7951

Browse files
committed
Add function to compute statistics about a scheduled product
This is to be able to add hook script support for scheduled products because for this we need to be able to determine whether all jobs of a scheduled product are done (to execute the hook script in this case). The hook script is supposed to do automatic approval/disapproval of changes. Hence it needs not only to know whether all jobs are done but also the state/result they ended up with. So this function returns these kinds of statistics instead of a binary "all done". Maybe it will need to be changed to return more high level statistics (like "all passed"), though. Related ticket: https://progress.opensuse.org/issues/184690
1 parent fe96ee5 commit 76b7951

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

lib/OpenQA/Schema/Result/ScheduledProducts.pm

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package OpenQA::Schema::Result::ScheduledProducts;
77
use Mojo::Base 'DBIx::Class::Core', -signatures;
88

99
use Mojo::Base -base, -signatures;
10+
use DBI qw(:sql_types);
1011
use DBIx::Class::Timestamps 'now';
1112
use Exporter 'import';
1213
use File::Basename;
@@ -962,4 +963,93 @@ sub cancel ($self, $reason = undef) {
962963
return $count;
963964
}
964965

966+
967+
=head2 job_statistics
968+
969+
Returns job statistics about the scheduled product.
970+
971+
This allows to determine whether all jobs are done and whether all jobs have
972+
passed. If jobs have been cloned/restarted then only the state/result of the
973+
latest job is taken into account.
974+
975+
The statistics are returned as nested hash references with one key per present
976+
state on outer level and one key per present result on inner level:
977+
978+
{
979+
done => {failed => {job_ids => [5057]}, incomplete => {job_ids => [5056]}}
980+
}
981+
982+
=cut
983+
984+
sub job_statistics ($self) {
985+
my $sth = $self->result_source->schema->storage->dbh->prepare(
986+
<<~'END_SQL'
987+
WITH RECURSIVE
988+
-- get the initial set of jobs in the scheduled product
989+
initial_job_ids AS (
990+
SELECT
991+
jobs.id AS job_id
992+
FROM
993+
scheduled_products
994+
JOIN jobs ON scheduled_products.id = jobs.scheduled_product_id
995+
WHERE
996+
scheduled_products.id = ?
997+
),
998+
-- find more recent jobs for each initial job recursively
999+
latest_id_resolver AS (
1000+
-- start with each job_id from initial_job_ids
1001+
SELECT
1002+
ij.job_id,
1003+
ij.job_id AS latest_job_id,
1004+
1 AS level
1005+
FROM
1006+
initial_job_ids AS ij
1007+
UNION ALL
1008+
-- find the clone_id for the current latest_job_id
1009+
SELECT
1010+
lir.job_id,
1011+
j.clone_id AS latest_job_id,
1012+
lir.level + 1 AS level
1013+
FROM
1014+
jobs AS j
1015+
JOIN latest_id_resolver AS lir ON lir.latest_job_id = j.id
1016+
-- limit the recursion
1017+
WHERE
1018+
lir.level < 50
1019+
),
1020+
-- filter jobs to only get the latest
1021+
most_recent_jobs AS (
1022+
SELECT DISTINCT ON (job_id)
1023+
job_id as initial_job_id,
1024+
latest_job_id,
1025+
mrj.state as latest_job_state,
1026+
mrj.result as latest_job_result,
1027+
level as chain_length
1028+
FROM
1029+
latest_id_resolver
1030+
JOIN jobs AS mrj ON mrj.id = latest_job_id
1031+
WHERE
1032+
latest_job_id IS NOT NULL
1033+
ORDER BY
1034+
job_id,
1035+
level DESC
1036+
)
1037+
SELECT
1038+
latest_job_state,
1039+
latest_job_result,
1040+
array_agg(latest_job_id) as job_ids
1041+
FROM
1042+
most_recent_jobs
1043+
WHERE
1044+
latest_job_id IS NOT NULL
1045+
GROUP BY
1046+
latest_job_state,
1047+
latest_job_result
1048+
END_SQL
1049+
);
1050+
$sth->bind_param(1, $self->id, SQL_BIGINT);
1051+
$sth->execute;
1052+
return $sth->fetchall_hashref([qw(latest_job_state latest_job_result)]);
1053+
}
1054+
9651055
1;

0 commit comments

Comments
 (0)