@@ -1957,15 +1957,57 @@ where
19571957
19581958 async fn get_status_page_data ( & self ) -> anyhow:: Result < PartialStatusPageData > {
19591959 let max_completed_requests = 7 ;
1960- let in_progress_requests_query = format ! (
1960+
1961+ // Returns in progress requests along with their associated jobs
1962+ let in_progress_query = format ! (
19611963 "
1962- SELECT {BENCHMARK_REQUEST_COLUMNS}
1963- FROM benchmark_request
1964- WHERE status = '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}'
1964+ WITH in_progress_requests AS (
1965+ SELECT
1966+ {BENCHMARK_REQUEST_COLUMNS}
1967+ FROM
1968+ benchmark_request
1969+ WHERE
1970+ status = '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}'
1971+ ORDER BY
1972+ completed_at
1973+ ), in_progress_jobs AS (
1974+ SELECT
1975+ request_tag AS tag,
1976+ ARRAY_AGG(
1977+ ROW(
1978+ job_queue.id,
1979+ job_queue.request_tag,
1980+ job_queue.target,
1981+ job_queue.backend,
1982+ job_queue.profile,
1983+ job_queue.benchmark_set,
1984+ job_queue.status,
1985+ job_queue.created_at,
1986+ job_queue.started_at,
1987+ job_queue.completed_at,
1988+ job_queue.retry,
1989+ job_queue.collector_name
1990+ )::TEXT
1991+ ) AS jobs
1992+ FROM
1993+ job_queue
1994+ LEFT JOIN in_progress_requests ON job_queue.request_tag = in_progress_requests.tag
1995+ GROUP BY
1996+ job_queue.request_tag
1997+ )
1998+ SELECT
1999+ in_progress_requests.*,
2000+ in_progress_jobs.jobs
2001+ FROM
2002+ in_progress_requests
2003+ LEFT JOIN
2004+ in_progress_jobs ON in_progress_requests.tag = in_progress_jobs.tag;
19652005 "
19662006 ) ;
2007+
19672008 // Gets requests along with how long the request took (latest job finish
1968- // - earliest job start) and associated errors with the request
2009+ // - earliest job start) and associated errors with the request if they
2010+ // exist
19692011 let completed_requests_query = format ! (
19702012 "
19712013 WITH completed AS (
@@ -2023,12 +2065,20 @@ where
20232065 "
20242066 ) ;
20252067
2026- let in_progress_requests : Vec < BenchmarkRequest > = self
2068+ let in_progress : Vec < ( BenchmarkRequest , Vec < BenchmarkJob > ) > = self
20272069 . conn ( )
2028- . query ( & in_progress_requests_query , & [ ] )
2070+ . query ( & in_progress_query , & [ ] )
20292071 . await ?
20302072 . iter ( )
2031- . map ( row_to_benchmark_request)
2073+ . map ( |it| {
2074+ let benchmark_request = row_to_benchmark_request ( it) ;
2075+ let jobs: Vec < BenchmarkJob > = it
2076+ . get :: < _ , Vec < String > > ( "jobs" )
2077+ . iter ( )
2078+ . map ( |it| benchmark_job_str_to_type ( it) . unwrap ( ) )
2079+ . collect ( ) ;
2080+ ( benchmark_request, jobs)
2081+ } )
20322082 . collect ( ) ;
20332083
20342084 let completed_requests: Vec < ( BenchmarkRequest , String , Vec < String > ) > = self
@@ -2039,7 +2089,10 @@ where
20392089 . map ( |it| {
20402090 (
20412091 row_to_benchmark_request ( it) ,
2092+ // Duration being a string feels odd, but we don't need to
2093+ // perform any computations on it
20422094 it. get :: < _ , String > ( 9 ) ,
2095+ // The errors, if there are none this will be an empty vector
20432096 it. get :: < _ , Vec < String > > ( 10 ) ,
20442097 )
20452098 } )
@@ -2115,10 +2168,10 @@ where
21152168 in_progress_jobs. push ( job) ;
21162169 }
21172170
2171+
21182172 Ok ( PartialStatusPageData {
21192173 completed_requests,
2120- in_progress_jobs,
2121- in_progress_requests,
2174+ in_progress,
21222175 } )
21232176 }
21242177}
@@ -2179,6 +2232,96 @@ fn row_to_benchmark_request(row: &Row) -> BenchmarkRequest {
21792232 }
21802233}
21812234
2235+ fn parse_timestamp ( cell : & str ) -> anyhow:: Result < Option < DateTime < Utc > > > {
2236+ if cell. is_empty ( ) {
2237+ Ok ( None )
2238+ } else {
2239+ // Massage postgres date string into something we can parse in Rust
2240+ // to a date
2241+ let raw_date = cell. trim_matches ( '"' ) . replace ( ' ' , "T" ) + ":00" ;
2242+ Ok ( Some (
2243+ DateTime :: parse_from_rfc3339 ( & raw_date) ?. with_timezone ( & Utc ) ,
2244+ ) )
2245+ }
2246+ }
2247+
2248+ fn benchmark_job_str_to_type ( src : & str ) -> anyhow:: Result < BenchmarkJob > {
2249+ let line = src. trim_start_matches ( '(' ) . trim_end_matches ( ')' ) ;
2250+
2251+ let mut col = line. split ( ',' ) ;
2252+
2253+ let id: u32 = col. next ( ) . ok_or_else ( || anyhow:: anyhow!( "id" ) ) ?. parse ( ) ?;
2254+ let request_tag = col
2255+ . next ( )
2256+ . ok_or_else ( || anyhow:: anyhow!( "request_tag" ) ) ?
2257+ . to_owned ( ) ;
2258+ let target = col
2259+ . next ( )
2260+ . ok_or_else ( || anyhow:: anyhow!( "target" ) ) ?
2261+ . parse :: < Target > ( )
2262+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
2263+ let backend = col
2264+ . next ( )
2265+ . ok_or_else ( || anyhow:: anyhow!( "backend" ) ) ?
2266+ . parse :: < CodegenBackend > ( )
2267+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
2268+ let profile = col
2269+ . next ( )
2270+ . ok_or_else ( || anyhow:: anyhow!( "profile" ) ) ?
2271+ . parse :: < Profile > ( )
2272+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
2273+ let benchmark_set = BenchmarkSet (
2274+ col. next ( )
2275+ . ok_or_else ( || anyhow:: anyhow!( "benchmark_set" ) ) ?
2276+ . parse ( ) ?,
2277+ ) ;
2278+
2279+ let status_str = col. next ( ) . ok_or_else ( || anyhow:: anyhow!( "status" ) ) ?;
2280+ let created_at = parse_timestamp ( col. next ( ) . ok_or_else ( || anyhow:: anyhow!( "created_at" ) ) ?) ?
2281+ . ok_or_else ( || anyhow:: anyhow!( "created_at missing" ) ) ?;
2282+
2283+ let started_at = parse_timestamp ( col. next ( ) . unwrap_or ( "" ) ) ?;
2284+ let completed_at = parse_timestamp ( col. next ( ) . unwrap_or ( "" ) ) ?;
2285+ let retry: u32 = col
2286+ . next ( )
2287+ . ok_or_else ( || anyhow:: anyhow!( "retry" ) ) ?
2288+ . parse ( ) ?;
2289+ let collector_name_raw = col. next ( ) . unwrap_or ( "" ) . to_owned ( ) ;
2290+
2291+ let status = match status_str {
2292+ BENCHMARK_JOB_STATUS_QUEUED_STR => BenchmarkJobStatus :: Queued ,
2293+
2294+ BENCHMARK_JOB_STATUS_IN_PROGRESS_STR => BenchmarkJobStatus :: InProgress {
2295+ started_at : started_at. ok_or_else ( || anyhow:: anyhow!( "started_at missing" ) ) ?,
2296+ collector_name : collector_name_raw,
2297+ } ,
2298+
2299+ BENCHMARK_JOB_STATUS_SUCCESS_STR | BENCHMARK_JOB_STATUS_FAILURE_STR => {
2300+ BenchmarkJobStatus :: Completed {
2301+ started_at : started_at. ok_or_else ( || anyhow:: anyhow!( "started_at missing" ) ) ?,
2302+ completed_at : completed_at
2303+ . ok_or_else ( || anyhow:: anyhow!( "completed_at missing" ) ) ?,
2304+ collector_name : collector_name_raw,
2305+ success : status_str == BENCHMARK_JOB_STATUS_SUCCESS_STR ,
2306+ }
2307+ }
2308+
2309+ _ => anyhow:: bail!( "unknown status `{status_str}`" ) ,
2310+ } ;
2311+
2312+ Ok ( BenchmarkJob {
2313+ id,
2314+ target,
2315+ backend,
2316+ profile,
2317+ request_tag,
2318+ benchmark_set,
2319+ created_at,
2320+ status,
2321+ deque_counter : retry,
2322+ } )
2323+ }
2324+
21822325fn parse_artifact_id ( ty : & str , sha : & str , date : Option < DateTime < Utc > > ) -> ArtifactId {
21832326 match ty {
21842327 "master" => ArtifactId :: Commit ( Commit {
0 commit comments