Skip to content

Commit 7f78922

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 7f78922

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

lib/OpenQA/Schema/Result/ScheduledProducts.pm

Lines changed: 94 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,97 @@ 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 => {
980+
failed => {job_count => 1, job_ids => [5057]},
981+
incomplete => {job_count => 1, job_ids => [5056]}
982+
}
983+
}
984+
985+
=cut
986+
987+
sub job_statistics ($self) {
988+
my $sth = $self->result_source->schema->storage->dbh->prepare(
989+
<<~'END_SQL'
990+
WITH RECURSIVE
991+
-- get the initial set of jobs in the scheduled product
992+
initial_job_ids AS (
993+
SELECT
994+
jobs.id AS job_id
995+
FROM
996+
scheduled_products
997+
JOIN jobs ON scheduled_products.id = jobs.scheduled_product_id
998+
WHERE
999+
scheduled_products.id = ?
1000+
),
1001+
-- find more recent jobs for each initial job recursively
1002+
latest_id_resolver AS (
1003+
-- start with each job_id from initial_job_ids
1004+
SELECT
1005+
ij.job_id,
1006+
ij.job_id AS latest_job_id,
1007+
1 AS level
1008+
FROM
1009+
initial_job_ids AS ij
1010+
UNION ALL
1011+
-- find the clone_id for the current latest_job_id
1012+
SELECT
1013+
lir.job_id,
1014+
j.clone_id AS latest_job_id,
1015+
lir.level + 1 AS level
1016+
FROM
1017+
jobs AS j
1018+
JOIN latest_id_resolver AS lir ON lir.latest_job_id = j.id
1019+
-- limit the recursion
1020+
WHERE
1021+
lir.level < 50
1022+
),
1023+
-- filter jobs to only get the latest
1024+
most_recent_jobs AS (
1025+
SELECT DISTINCT ON (job_id)
1026+
job_id as initial_job_id,
1027+
latest_job_id,
1028+
mrj.state as latest_job_state,
1029+
mrj.result as latest_job_result,
1030+
level as chain_length
1031+
FROM
1032+
latest_id_resolver
1033+
JOIN jobs AS mrj ON mrj.id = latest_job_id
1034+
WHERE
1035+
latest_job_id IS NOT NULL
1036+
ORDER BY
1037+
job_id,
1038+
level DESC
1039+
)
1040+
SELECT
1041+
latest_job_state,
1042+
latest_job_result,
1043+
count(latest_job_result) as job_count,
1044+
array_agg(latest_job_id) as job_ids
1045+
FROM
1046+
most_recent_jobs
1047+
WHERE
1048+
latest_job_id IS NOT NULL
1049+
GROUP BY
1050+
latest_job_state,
1051+
latest_job_result
1052+
END_SQL
1053+
);
1054+
$sth->bind_param(1, $self->id, SQL_BIGINT);
1055+
$sth->execute;
1056+
return $sth->fetchall_hashref([qw(latest_job_state latest_job_result)]);
1057+
}
1058+
9651059
1;

0 commit comments

Comments
 (0)