@@ -4,10 +4,10 @@ use crate::{
4
4
ArtifactCollection , ArtifactId , ArtifactIdNumber , Benchmark , BenchmarkJob ,
5
5
BenchmarkJobConclusion , BenchmarkJobStatus , BenchmarkRequest , BenchmarkRequestIndex ,
6
6
BenchmarkRequestStatus , BenchmarkRequestType , BenchmarkSet , CodegenBackend , CollectionId ,
7
- CollectorConfig , Commit , CommitType , CompileBenchmark , Date , Index , Profile , QueuedCommit ,
8
- Scenario , Target , BENCHMARK_JOB_STATUS_FAILURE_STR , BENCHMARK_JOB_STATUS_IN_PROGRESS_STR ,
9
- BENCHMARK_JOB_STATUS_QUEUED_STR , BENCHMARK_JOB_STATUS_SUCCESS_STR ,
10
- BENCHMARK_REQUEST_MASTER_STR , BENCHMARK_REQUEST_RELEASE_STR ,
7
+ CollectorConfig , Commit , CommitType , CompileBenchmark , Date , Index , PartialStatusPageData ,
8
+ Profile , QueuedCommit , Scenario , Target , BENCHMARK_JOB_STATUS_FAILURE_STR ,
9
+ BENCHMARK_JOB_STATUS_IN_PROGRESS_STR , BENCHMARK_JOB_STATUS_QUEUED_STR ,
10
+ BENCHMARK_JOB_STATUS_SUCCESS_STR , BENCHMARK_REQUEST_MASTER_STR , BENCHMARK_REQUEST_RELEASE_STR ,
11
11
BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR , BENCHMARK_REQUEST_STATUS_COMPLETED_STR ,
12
12
BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR , BENCHMARK_REQUEST_STATUS_WAITING_FOR_ARTIFACTS_STR ,
13
13
BENCHMARK_REQUEST_TRY_STR ,
@@ -21,8 +21,8 @@ use std::str::FromStr;
21
21
use std:: sync:: Arc ;
22
22
use std:: time:: Duration ;
23
23
use tokio:: sync:: Mutex ;
24
- use tokio_postgres:: GenericClient ;
25
24
use tokio_postgres:: Statement ;
25
+ use tokio_postgres:: { GenericClient , Row } ;
26
26
27
27
pub struct Postgres ( String , std:: sync:: Once ) ;
28
28
@@ -663,6 +663,9 @@ impl PostgresConnection {
663
663
}
664
664
}
665
665
666
+ const BENCHMARK_REQUEST_COLUMNS : & str =
667
+ "tag, parent_sha, pr, commit_type, status, created_at, completed_at, backends, profiles" ;
668
+
666
669
#[ async_trait:: async_trait]
667
670
impl < P > Connection for P
668
671
where
@@ -1594,16 +1597,7 @@ where
1594
1597
async fn load_pending_benchmark_requests ( & self ) -> anyhow:: Result < Vec < BenchmarkRequest > > {
1595
1598
let query = format ! (
1596
1599
r#"
1597
- SELECT
1598
- tag,
1599
- parent_sha,
1600
- pr,
1601
- commit_type,
1602
- status,
1603
- created_at,
1604
- completed_at,
1605
- backends,
1606
- profiles
1600
+ SELECT {BENCHMARK_REQUEST_COLUMNS}
1607
1601
FROM benchmark_request
1608
1602
WHERE status IN('{BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR}', '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}')"#
1609
1603
) ;
@@ -1616,59 +1610,7 @@ where
1616
1610
1617
1611
let requests = rows
1618
1612
. into_iter ( )
1619
- . map ( |row| {
1620
- let tag = row. get :: < _ , Option < String > > ( 0 ) ;
1621
- let parent_sha = row. get :: < _ , Option < String > > ( 1 ) ;
1622
- let pr = row. get :: < _ , Option < i32 > > ( 2 ) ;
1623
- let commit_type = row. get :: < _ , & str > ( 3 ) ;
1624
- let status = row. get :: < _ , & str > ( 4 ) ;
1625
- let created_at = row. get :: < _ , DateTime < Utc > > ( 5 ) ;
1626
- let completed_at = row. get :: < _ , Option < DateTime < Utc > > > ( 6 ) ;
1627
- let backends = row. get :: < _ , String > ( 7 ) ;
1628
- let profiles = row. get :: < _ , String > ( 8 ) ;
1629
-
1630
- let pr = pr. map ( |v| v as u32 ) ;
1631
-
1632
- let status =
1633
- BenchmarkRequestStatus :: from_str_and_completion_date ( status, completed_at)
1634
- . expect ( "Invalid BenchmarkRequestStatus data in the database" ) ;
1635
-
1636
- match commit_type {
1637
- BENCHMARK_REQUEST_TRY_STR => BenchmarkRequest {
1638
- commit_type : BenchmarkRequestType :: Try {
1639
- sha : tag,
1640
- parent_sha,
1641
- pr : pr. expect ( "Try commit in the DB without a PR" ) ,
1642
- } ,
1643
- created_at,
1644
- status,
1645
- backends,
1646
- profiles,
1647
- } ,
1648
- BENCHMARK_REQUEST_MASTER_STR => BenchmarkRequest {
1649
- commit_type : BenchmarkRequestType :: Master {
1650
- sha : tag. expect ( "Master commit in the DB without a SHA" ) ,
1651
- parent_sha : parent_sha
1652
- . expect ( "Master commit in the DB without a parent SHA" ) ,
1653
- pr : pr. expect ( "Master commit in the DB without a PR" ) ,
1654
- } ,
1655
- created_at,
1656
- status,
1657
- backends,
1658
- profiles,
1659
- } ,
1660
- BENCHMARK_REQUEST_RELEASE_STR => BenchmarkRequest {
1661
- commit_type : BenchmarkRequestType :: Release {
1662
- tag : tag. expect ( "Release commit in the DB without a SHA" ) ,
1663
- } ,
1664
- created_at,
1665
- status,
1666
- backends,
1667
- profiles,
1668
- } ,
1669
- _ => panic ! ( "Invalid `commit_type` for `BenchmarkRequest` {commit_type}" , ) ,
1670
- }
1671
- } )
1613
+ . map ( |it| row_to_benchmark_request ( & it) )
1672
1614
. collect ( ) ;
1673
1615
Ok ( requests)
1674
1616
}
@@ -1970,6 +1912,223 @@ where
1970
1912
. context ( "Failed to mark benchmark job as completed" ) ?;
1971
1913
Ok ( ( ) )
1972
1914
}
1915
+
1916
+ async fn get_status_page_data ( & self ) -> anyhow:: Result < PartialStatusPageData > {
1917
+ let max_completed_requests = 7 ;
1918
+ let in_progress_requests_query = format ! (
1919
+ "
1920
+ SELECT {BENCHMARK_REQUEST_COLUMNS}
1921
+ FROM benchmark_requests
1922
+ WHERE status = '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}'
1923
+ "
1924
+ ) ;
1925
+ // Gets requests along with how long the request took (latest job finish
1926
+ // - earliest job start) and associated errors with the request
1927
+ let completed_requests_query = format ! (
1928
+ "
1929
+ WITH completed AS (
1930
+ SELECT
1931
+ {BENCHMARK_REQUEST_COLUMNS}
1932
+ FROM
1933
+ benchmark_request
1934
+ WHERE
1935
+ status = '{BENCHMARK_REQUEST_STATUS_COMPLETED_STR}'
1936
+ ORDER BY
1937
+ completed_at
1938
+ DESC LIMIT {max_completed_requests}
1939
+ ), jobs AS (
1940
+ SELECT
1941
+ completed.tag,
1942
+ job_queue.started_at,
1943
+ job_queue.completed_at
1944
+ FROM
1945
+ job_queue
1946
+ LEFT JOIN completed ON job_queue.request_tag = completed.tag
1947
+ ), stats AS (
1948
+ SELECT
1949
+ tag,
1950
+ MAX(jobs.completed_at - jobs.started_at) AS duration
1951
+ FROM
1952
+ jobs
1953
+ GROUP BY
1954
+ tag
1955
+ ), artifacts AS (
1956
+ SELECT
1957
+ artifact.id,
1958
+ \" name\"
1959
+ FROM
1960
+ artifact
1961
+ LEFT JOIN completed ON artifact.name = completed.tag
1962
+ ), errors AS (
1963
+ SELECT
1964
+ artifacts.name AS tag,
1965
+ ARRAY_AGG(error) AS errors
1966
+ FROM
1967
+ error
1968
+ LEFT JOIN
1969
+ artifacts ON error.aid = artifacts.id
1970
+ GROUP BY
1971
+ tag
1972
+ )
1973
+ SELECT
1974
+ completed.*,
1975
+ stats.*,
1976
+ errors.errors AS errors
1977
+ FROM
1978
+ completed
1979
+ LEFT JOIN stats ON stats.tag = completed.tag
1980
+ LEFT JOIN errors ON errors.tag = completed.tag;
1981
+ "
1982
+ ) ;
1983
+
1984
+ let in_progress_requests: Vec < BenchmarkRequest > = self
1985
+ . conn ( )
1986
+ . query ( & in_progress_requests_query, & [ ] )
1987
+ . await ?
1988
+ . iter ( )
1989
+ . map ( row_to_benchmark_request)
1990
+ . collect ( ) ;
1991
+
1992
+ let completed_requests: Vec < ( BenchmarkRequest , u64 , Vec < String > ) > = self
1993
+ . conn ( )
1994
+ . query ( & completed_requests_query, & [ ] )
1995
+ . await ?
1996
+ . iter ( )
1997
+ . map ( |it| {
1998
+ (
1999
+ row_to_benchmark_request ( it) ,
2000
+ it. get :: < _ , i64 > ( 9 ) as u64 ,
2001
+ it. get :: < _ , Vec < String > > ( 10 ) ,
2002
+ )
2003
+ } )
2004
+ . collect ( ) ;
2005
+
2006
+ let in_progress_tags: Vec < & str > = in_progress_requests
2007
+ . iter ( )
2008
+ . map ( |it| it. tag ( ) . unwrap ( ) )
2009
+ . collect ( ) ;
2010
+
2011
+ // We don't do a status check on the jobs as we want to return all jobs,
2012
+ // irrespective of status, that are attached to an inprogress
2013
+ // benchmark_request
2014
+ let rows = self
2015
+ . conn ( )
2016
+ . query (
2017
+ "SELECT
2018
+ id,
2019
+ target,
2020
+ backend,
2021
+ profile,
2022
+ request_tag,
2023
+ benchmark_set,
2024
+ created_at,
2025
+ status,
2026
+ started_at,
2027
+ collector_name,
2028
+ completed_at,
2029
+ retry
2030
+ FROM
2031
+ job_queue WHERE job_queue.tag IN ($1);" ,
2032
+ & [ & in_progress_tags] ,
2033
+ )
2034
+ . await ?;
2035
+
2036
+ let mut in_progress_jobs = vec ! [ ] ;
2037
+ for row in rows {
2038
+ let status_str = row. get :: < _ , & str > ( 7 ) ;
2039
+ let status = match status_str {
2040
+ BENCHMARK_JOB_STATUS_QUEUED_STR => BenchmarkJobStatus :: Queued ,
2041
+ BENCHMARK_JOB_STATUS_IN_PROGRESS_STR => BenchmarkJobStatus :: InProgress {
2042
+ started_at : row. get :: < _ , DateTime < Utc > > ( 8 ) ,
2043
+ collector_name : row. get :: < _ , String > ( 9 ) ,
2044
+ } ,
2045
+ BENCHMARK_JOB_STATUS_SUCCESS_STR | BENCHMARK_JOB_STATUS_FAILURE_STR => {
2046
+ BenchmarkJobStatus :: Completed {
2047
+ started_at : row. get :: < _ , DateTime < Utc > > ( 8 ) ,
2048
+ collector_name : row. get :: < _ , String > ( 9 ) ,
2049
+ success : status_str == BENCHMARK_JOB_STATUS_SUCCESS_STR ,
2050
+ completed_at : row. get :: < _ , DateTime < Utc > > ( 10 ) ,
2051
+ }
2052
+ }
2053
+ _ => panic ! ( "Invalid benchmark job status: {status_str}" ) ,
2054
+ } ;
2055
+
2056
+ let job = BenchmarkJob {
2057
+ id : row. get :: < _ , i32 > ( 0 ) as u32 ,
2058
+ target : Target :: from_str ( row. get :: < _ , & str > ( 1 ) ) . map_err ( |e| anyhow:: anyhow!( e) ) ?,
2059
+ backend : CodegenBackend :: from_str ( row. get :: < _ , & str > ( 2 ) )
2060
+ . map_err ( |e| anyhow:: anyhow!( e) ) ?,
2061
+ profile : Profile :: from_str ( row. get :: < _ , & str > ( 3 ) )
2062
+ . map_err ( |e| anyhow:: anyhow!( e) ) ?,
2063
+ request_tag : row. get :: < _ , String > ( 4 ) ,
2064
+ benchmark_set : BenchmarkSet ( row. get :: < _ , i32 > ( 5 ) as u32 ) ,
2065
+ created_at : row. get :: < _ , DateTime < Utc > > ( 6 ) ,
2066
+ // The job is now in an in_progress state
2067
+ status,
2068
+ retry : row. get :: < _ , i32 > ( 11 ) as u32 ,
2069
+ } ;
2070
+
2071
+ in_progress_jobs. push ( job) ;
2072
+ }
2073
+
2074
+ Ok ( PartialStatusPageData {
2075
+ completed_requests,
2076
+ in_progress_jobs,
2077
+ in_progress_requests,
2078
+ } )
2079
+ }
2080
+ }
2081
+
2082
+ fn row_to_benchmark_request ( row : & Row ) -> BenchmarkRequest {
2083
+ let tag = row. get :: < _ , Option < String > > ( 0 ) ;
2084
+ let parent_sha = row. get :: < _ , Option < String > > ( 1 ) ;
2085
+ let pr = row. get :: < _ , Option < i32 > > ( 2 ) ;
2086
+ let commit_type = row. get :: < _ , & str > ( 3 ) ;
2087
+ let status = row. get :: < _ , & str > ( 4 ) ;
2088
+ let created_at = row. get :: < _ , DateTime < Utc > > ( 5 ) ;
2089
+ let completed_at = row. get :: < _ , Option < DateTime < Utc > > > ( 6 ) ;
2090
+ let backends = row. get :: < _ , String > ( 7 ) ;
2091
+ let profiles = row. get :: < _ , String > ( 8 ) ;
2092
+
2093
+ let pr = pr. map ( |v| v as u32 ) ;
2094
+
2095
+ let status = BenchmarkRequestStatus :: from_str_and_completion_date ( status, completed_at)
2096
+ . expect ( "Invalid BenchmarkRequestStatus data in the database" ) ;
2097
+
2098
+ match commit_type {
2099
+ BENCHMARK_REQUEST_TRY_STR => BenchmarkRequest {
2100
+ commit_type : BenchmarkRequestType :: Try {
2101
+ sha : tag,
2102
+ parent_sha,
2103
+ pr : pr. expect ( "Try commit in the DB without a PR" ) ,
2104
+ } ,
2105
+ created_at,
2106
+ status,
2107
+ backends,
2108
+ profiles,
2109
+ } ,
2110
+ BENCHMARK_REQUEST_MASTER_STR => BenchmarkRequest {
2111
+ commit_type : BenchmarkRequestType :: Master {
2112
+ sha : tag. expect ( "Master commit in the DB without a SHA" ) ,
2113
+ parent_sha : parent_sha. expect ( "Master commit in the DB without a parent SHA" ) ,
2114
+ pr : pr. expect ( "Master commit in the DB without a PR" ) ,
2115
+ } ,
2116
+ created_at,
2117
+ status,
2118
+ backends,
2119
+ profiles,
2120
+ } ,
2121
+ BENCHMARK_REQUEST_RELEASE_STR => BenchmarkRequest {
2122
+ commit_type : BenchmarkRequestType :: Release {
2123
+ tag : tag. expect ( "Release commit in the DB without a SHA" ) ,
2124
+ } ,
2125
+ created_at,
2126
+ status,
2127
+ backends,
2128
+ profiles,
2129
+ } ,
2130
+ _ => panic ! ( "Invalid `commit_type` for `BenchmarkRequest` {commit_type}" , ) ,
2131
+ }
1973
2132
}
1974
2133
1975
2134
fn parse_artifact_id ( ty : & str , sha : & str , date : Option < DateTime < Utc > > ) -> ArtifactId {
0 commit comments