@@ -4,10 +4,10 @@ use crate::{
44 ArtifactCollection , ArtifactId , ArtifactIdNumber , Benchmark , BenchmarkJob ,
55 BenchmarkJobConclusion , BenchmarkJobStatus , BenchmarkRequest , BenchmarkRequestIndex ,
66 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 ,
1111 BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR , BENCHMARK_REQUEST_STATUS_COMPLETED_STR ,
1212 BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR , BENCHMARK_REQUEST_STATUS_WAITING_FOR_ARTIFACTS_STR ,
1313 BENCHMARK_REQUEST_TRY_STR ,
@@ -21,8 +21,8 @@ use std::str::FromStr;
2121use std:: sync:: Arc ;
2222use std:: time:: Duration ;
2323use tokio:: sync:: Mutex ;
24- use tokio_postgres:: GenericClient ;
2524use tokio_postgres:: Statement ;
25+ use tokio_postgres:: { GenericClient , Row } ;
2626
2727pub struct Postgres ( String , std:: sync:: Once ) ;
2828
@@ -666,6 +666,9 @@ impl PostgresConnection {
666666 }
667667}
668668
669+ const BENCHMARK_REQUEST_COLUMNS : & str =
670+ "tag, parent_sha, pr, commit_type, status, created_at, completed_at, backends, profiles, commit_date" ;
671+
669672#[ async_trait:: async_trait]
670673impl < P > Connection for P
671674where
@@ -1602,17 +1605,7 @@ where
16021605 async fn load_pending_benchmark_requests ( & self ) -> anyhow:: Result < Vec < BenchmarkRequest > > {
16031606 let query = format ! (
16041607 r#"
1605- SELECT
1606- tag,
1607- parent_sha,
1608- pr,
1609- commit_type,
1610- status,
1611- created_at,
1612- completed_at,
1613- backends,
1614- profiles,
1615- commit_date
1608+ SELECT {BENCHMARK_REQUEST_COLUMNS}
16161609 FROM benchmark_request
16171610 WHERE status IN('{BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR}', '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}')"#
16181611 ) ;
@@ -1625,63 +1618,7 @@ where
16251618
16261619 let requests = rows
16271620 . into_iter ( )
1628- . map ( |row| {
1629- let tag = row. get :: < _ , Option < String > > ( 0 ) ;
1630- let parent_sha = row. get :: < _ , Option < String > > ( 1 ) ;
1631- let pr = row. get :: < _ , Option < i32 > > ( 2 ) ;
1632- let commit_type = row. get :: < _ , & str > ( 3 ) ;
1633- let status = row. get :: < _ , & str > ( 4 ) ;
1634- let created_at = row. get :: < _ , DateTime < Utc > > ( 5 ) ;
1635- let completed_at = row. get :: < _ , Option < DateTime < Utc > > > ( 6 ) ;
1636- let backends = row. get :: < _ , String > ( 7 ) ;
1637- let profiles = row. get :: < _ , String > ( 8 ) ;
1638- let commit_date = row. get :: < _ , Option < DateTime < Utc > > > ( 9 ) ;
1639-
1640- let pr = pr. map ( |v| v as u32 ) ;
1641-
1642- let status =
1643- BenchmarkRequestStatus :: from_str_and_completion_date ( status, completed_at)
1644- . expect ( "Invalid BenchmarkRequestStatus data in the database" ) ;
1645-
1646- match commit_type {
1647- BENCHMARK_REQUEST_TRY_STR => BenchmarkRequest {
1648- commit_type : BenchmarkRequestType :: Try {
1649- sha : tag,
1650- parent_sha,
1651- pr : pr. expect ( "Try commit in the DB without a PR" ) ,
1652- } ,
1653- commit_date,
1654- created_at,
1655- status,
1656- backends,
1657- profiles,
1658- } ,
1659- BENCHMARK_REQUEST_MASTER_STR => BenchmarkRequest {
1660- commit_type : BenchmarkRequestType :: Master {
1661- sha : tag. expect ( "Master commit in the DB without a SHA" ) ,
1662- parent_sha : parent_sha
1663- . expect ( "Master commit in the DB without a parent SHA" ) ,
1664- pr : pr. expect ( "Master commit in the DB without a PR" ) ,
1665- } ,
1666- commit_date,
1667- created_at,
1668- status,
1669- backends,
1670- profiles,
1671- } ,
1672- BENCHMARK_REQUEST_RELEASE_STR => BenchmarkRequest {
1673- commit_type : BenchmarkRequestType :: Release {
1674- tag : tag. expect ( "Release commit in the DB without a SHA" ) ,
1675- } ,
1676- commit_date,
1677- created_at,
1678- status,
1679- backends,
1680- profiles,
1681- } ,
1682- _ => panic ! ( "Invalid `commit_type` for `BenchmarkRequest` {commit_type}" , ) ,
1683- }
1684- } )
1621+ . map ( |it| row_to_benchmark_request ( & it) )
16851622 . collect ( ) ;
16861623 Ok ( requests)
16871624 }
@@ -2017,6 +1954,227 @@ where
20171954 . context ( "Failed to mark benchmark job as completed" ) ?;
20181955 Ok ( ( ) )
20191956 }
1957+
1958+ async fn get_status_page_data ( & self ) -> anyhow:: Result < PartialStatusPageData > {
1959+ let max_completed_requests = 7 ;
1960+ let in_progress_requests_query = format ! (
1961+ "
1962+ SELECT {BENCHMARK_REQUEST_COLUMNS}
1963+ FROM benchmark_requests
1964+ WHERE status = '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}'
1965+ "
1966+ ) ;
1967+ // Gets requests along with how long the request took (latest job finish
1968+ // - earliest job start) and associated errors with the request
1969+ let completed_requests_query = format ! (
1970+ "
1971+ WITH completed AS (
1972+ SELECT
1973+ {BENCHMARK_REQUEST_COLUMNS}
1974+ FROM
1975+ benchmark_request
1976+ WHERE
1977+ status = '{BENCHMARK_REQUEST_STATUS_COMPLETED_STR}'
1978+ ORDER BY
1979+ completed_at
1980+ DESC LIMIT {max_completed_requests}
1981+ ), jobs AS (
1982+ SELECT
1983+ completed.tag,
1984+ job_queue.started_at,
1985+ job_queue.completed_at
1986+ FROM
1987+ job_queue
1988+ LEFT JOIN completed ON job_queue.request_tag = completed.tag
1989+ ), stats AS (
1990+ SELECT
1991+ tag,
1992+ MAX(jobs.completed_at - jobs.started_at) AS duration
1993+ FROM
1994+ jobs
1995+ GROUP BY
1996+ tag
1997+ ), artifacts AS (
1998+ SELECT
1999+ artifact.id,
2000+ \" name\"
2001+ FROM
2002+ artifact
2003+ LEFT JOIN completed ON artifact.name = completed.tag
2004+ ), errors AS (
2005+ SELECT
2006+ artifacts.name AS tag,
2007+ ARRAY_AGG(error) AS errors
2008+ FROM
2009+ error
2010+ LEFT JOIN
2011+ artifacts ON error.aid = artifacts.id
2012+ GROUP BY
2013+ tag
2014+ )
2015+ SELECT
2016+ completed.*,
2017+ stats.*,
2018+ errors.errors AS errors
2019+ FROM
2020+ completed
2021+ LEFT JOIN stats ON stats.tag = completed.tag
2022+ LEFT JOIN errors ON errors.tag = completed.tag;
2023+ "
2024+ ) ;
2025+
2026+ let in_progress_requests: Vec < BenchmarkRequest > = self
2027+ . conn ( )
2028+ . query ( & in_progress_requests_query, & [ ] )
2029+ . await ?
2030+ . iter ( )
2031+ . map ( row_to_benchmark_request)
2032+ . collect ( ) ;
2033+
2034+ let completed_requests: Vec < ( BenchmarkRequest , u64 , Vec < String > ) > = self
2035+ . conn ( )
2036+ . query ( & completed_requests_query, & [ ] )
2037+ . await ?
2038+ . iter ( )
2039+ . map ( |it| {
2040+ (
2041+ row_to_benchmark_request ( it) ,
2042+ it. get :: < _ , i64 > ( 9 ) as u64 ,
2043+ it. get :: < _ , Vec < String > > ( 10 ) ,
2044+ )
2045+ } )
2046+ . collect ( ) ;
2047+
2048+ let in_progress_tags: Vec < & str > = in_progress_requests
2049+ . iter ( )
2050+ . map ( |it| it. tag ( ) . unwrap ( ) )
2051+ . collect ( ) ;
2052+
2053+ // We don't do a status check on the jobs as we want to return all jobs,
2054+ // irrespective of status, that are attached to an inprogress
2055+ // benchmark_request
2056+ let rows = self
2057+ . conn ( )
2058+ . query (
2059+ "SELECT
2060+ id,
2061+ target,
2062+ backend,
2063+ profile,
2064+ request_tag,
2065+ benchmark_set,
2066+ created_at,
2067+ status,
2068+ started_at,
2069+ collector_name,
2070+ completed_at,
2071+ retry
2072+ FROM
2073+ job_queue WHERE job_queue.tag IN ($1);" ,
2074+ & [ & in_progress_tags] ,
2075+ )
2076+ . await ?;
2077+
2078+ let mut in_progress_jobs = vec ! [ ] ;
2079+ for row in rows {
2080+ let status_str = row. get :: < _ , & str > ( 7 ) ;
2081+ let status = match status_str {
2082+ BENCHMARK_JOB_STATUS_QUEUED_STR => BenchmarkJobStatus :: Queued ,
2083+ BENCHMARK_JOB_STATUS_IN_PROGRESS_STR => BenchmarkJobStatus :: InProgress {
2084+ started_at : row. get :: < _ , DateTime < Utc > > ( 8 ) ,
2085+ collector_name : row. get :: < _ , String > ( 9 ) ,
2086+ } ,
2087+ BENCHMARK_JOB_STATUS_SUCCESS_STR | BENCHMARK_JOB_STATUS_FAILURE_STR => {
2088+ BenchmarkJobStatus :: Completed {
2089+ started_at : row. get :: < _ , DateTime < Utc > > ( 8 ) ,
2090+ collector_name : row. get :: < _ , String > ( 9 ) ,
2091+ success : status_str == BENCHMARK_JOB_STATUS_SUCCESS_STR ,
2092+ completed_at : row. get :: < _ , DateTime < Utc > > ( 10 ) ,
2093+ }
2094+ }
2095+ _ => panic ! ( "Invalid benchmark job status: {status_str}" ) ,
2096+ } ;
2097+
2098+ let job = BenchmarkJob {
2099+ id : row. get :: < _ , i32 > ( 0 ) as u32 ,
2100+ target : Target :: from_str ( row. get :: < _ , & str > ( 1 ) ) . map_err ( |e| anyhow:: anyhow!( e) ) ?,
2101+ backend : CodegenBackend :: from_str ( row. get :: < _ , & str > ( 2 ) )
2102+ . map_err ( |e| anyhow:: anyhow!( e) ) ?,
2103+ profile : Profile :: from_str ( row. get :: < _ , & str > ( 3 ) )
2104+ . map_err ( |e| anyhow:: anyhow!( e) ) ?,
2105+ request_tag : row. get :: < _ , String > ( 4 ) ,
2106+ benchmark_set : BenchmarkSet ( row. get :: < _ , i32 > ( 5 ) as u32 ) ,
2107+ created_at : row. get :: < _ , DateTime < Utc > > ( 6 ) ,
2108+ // The job is now in an in_progress state
2109+ status,
2110+ deque_counter : row. get :: < _ , i32 > ( 11 ) as u32 ,
2111+ } ;
2112+
2113+ in_progress_jobs. push ( job) ;
2114+ }
2115+
2116+ Ok ( PartialStatusPageData {
2117+ completed_requests,
2118+ in_progress_jobs,
2119+ in_progress_requests,
2120+ } )
2121+ }
2122+ }
2123+
2124+ fn row_to_benchmark_request ( row : & Row ) -> BenchmarkRequest {
2125+ let tag = row. get :: < _ , Option < String > > ( 0 ) ;
2126+ let parent_sha = row. get :: < _ , Option < String > > ( 1 ) ;
2127+ let pr = row. get :: < _ , Option < i32 > > ( 2 ) ;
2128+ let commit_type = row. get :: < _ , & str > ( 3 ) ;
2129+ let status = row. get :: < _ , & str > ( 4 ) ;
2130+ let created_at = row. get :: < _ , DateTime < Utc > > ( 5 ) ;
2131+ let completed_at = row. get :: < _ , Option < DateTime < Utc > > > ( 6 ) ;
2132+ let backends = row. get :: < _ , String > ( 7 ) ;
2133+ let profiles = row. get :: < _ , String > ( 8 ) ;
2134+ let commit_date = row. get :: < _ , Option < DateTime < Utc > > > ( 9 ) ;
2135+
2136+ let pr = pr. map ( |v| v as u32 ) ;
2137+
2138+ let status = BenchmarkRequestStatus :: from_str_and_completion_date ( status, completed_at)
2139+ . expect ( "Invalid BenchmarkRequestStatus data in the database" ) ;
2140+
2141+ match commit_type {
2142+ BENCHMARK_REQUEST_TRY_STR => BenchmarkRequest {
2143+ commit_type : BenchmarkRequestType :: Try {
2144+ sha : tag,
2145+ parent_sha,
2146+ pr : pr. expect ( "Try commit in the DB without a PR" ) ,
2147+ } ,
2148+ commit_date,
2149+ created_at,
2150+ status,
2151+ backends,
2152+ profiles,
2153+ } ,
2154+ BENCHMARK_REQUEST_MASTER_STR => BenchmarkRequest {
2155+ commit_type : BenchmarkRequestType :: Master {
2156+ sha : tag. expect ( "Master commit in the DB without a SHA" ) ,
2157+ parent_sha : parent_sha. expect ( "Master commit in the DB without a parent SHA" ) ,
2158+ pr : pr. expect ( "Master commit in the DB without a PR" ) ,
2159+ } ,
2160+ commit_date,
2161+ created_at,
2162+ status,
2163+ backends,
2164+ profiles,
2165+ } ,
2166+ BENCHMARK_REQUEST_RELEASE_STR => BenchmarkRequest {
2167+ commit_type : BenchmarkRequestType :: Release {
2168+ tag : tag. expect ( "Release commit in the DB without a SHA" ) ,
2169+ } ,
2170+ commit_date,
2171+ created_at,
2172+ status,
2173+ backends,
2174+ profiles,
2175+ } ,
2176+ _ => panic ! ( "Invalid `commit_type` for `BenchmarkRequest` {commit_type}" , ) ,
2177+ }
20202178}
20212179
20222180fn parse_artifact_id ( ty : & str , sha : & str , date : Option < DateTime < Utc > > ) -> ArtifactId {
0 commit comments