11mod utils;
22
3+ use crate :: github:: comparison_summary:: post_comparison_comment;
34use crate :: job_queue:: utils:: { parse_release_string, ExtractIf } ;
45use crate :: load:: { partition_in_place, SiteCtxt } ;
56use chrono:: Utc ;
67use collector:: benchmark_set:: benchmark_set_count;
78use database:: {
8- BenchmarkRequest , BenchmarkRequestIndex , BenchmarkRequestStatus , PendingBenchmarkRequests ,
9- Target ,
9+ BenchmarkRequest , BenchmarkRequestIndex , BenchmarkRequestStatus , BenchmarkRequestType , Date ,
10+ PendingBenchmarkRequests , QueuedCommit , Target ,
1011} ;
1112use parking_lot:: RwLock ;
1213use std:: { str:: FromStr , sync:: Arc } ;
13- use tokio:: time:: { self , Duration } ;
14+ use tokio:: time:: { self , Duration , MissedTickBehavior } ;
1415
1516pub fn run_new_queue ( ) -> bool {
1617 std:: env:: var ( "RUN_CRON" )
@@ -20,12 +21,13 @@ pub fn run_new_queue() -> bool {
2021}
2122
2223/// Store the latest master commits or do nothing if all of them are
23- /// already in the database
24+ /// already in the database.
25+ /// Returns `true` if at least one benchmark request was inserted.
2426async fn create_benchmark_request_master_commits (
2527 ctxt : & SiteCtxt ,
2628 conn : & dyn database:: pool:: Connection ,
2729 index : & BenchmarkRequestIndex ,
28- ) -> anyhow:: Result < ( ) > {
30+ ) -> anyhow:: Result < bool > {
2931 let now = Utc :: now ( ) ;
3032
3133 let master_commits = ctxt. get_master_commits ( ) ;
@@ -38,6 +40,7 @@ async fn create_benchmark_request_master_commits(
3840 // TODO; delete at some point in the future
3941 let cutoff: chrono:: DateTime < Utc > = chrono:: DateTime :: from_str ( "2025-08-27T00:00:00.000Z" ) ?;
4042
43+ let mut inserted = false ;
4144 for master_commit in master_commits {
4245 // We don't want to add masses of obsolete data
4346 if master_commit. time >= cutoff && !index. contains_tag ( & master_commit. sha ) {
@@ -51,18 +54,21 @@ async fn create_benchmark_request_master_commits(
5154 log:: info!( "Inserting master benchmark request {benchmark:?}" ) ;
5255 if let Err ( error) = conn. insert_benchmark_request ( & benchmark) . await {
5356 log:: error!( "Failed to insert master benchmark request: {error:?}" ) ;
57+ } else {
58+ inserted = true ;
5459 }
5560 }
5661 }
57- Ok ( ( ) )
62+ Ok ( inserted )
5863}
5964
6065/// Store the latest release commits or do nothing if all of them are
6166/// already in the database
67+ /// Returns `true` if at least one benchmark request was inserted.
6268async fn create_benchmark_request_releases (
6369 conn : & dyn database:: pool:: Connection ,
6470 index : & BenchmarkRequestIndex ,
65- ) -> anyhow:: Result < ( ) > {
71+ ) -> anyhow:: Result < bool > {
6672 let releases: String = reqwest:: get ( "https://static.rust-lang.org/manifests.txt" )
6773 . await ?
6874 . text ( )
@@ -76,16 +82,19 @@ async fn create_benchmark_request_releases(
7682 . filter_map ( parse_release_string)
7783 . take ( 20 ) ;
7884
85+ let mut inserted = false ;
7986 for ( name, commit_date) in releases {
8087 if commit_date >= cutoff && !index. contains_tag ( & name) {
8188 let release_request = BenchmarkRequest :: create_release ( & name, commit_date) ;
8289 log:: info!( "Inserting release benchmark request {release_request:?}" ) ;
8390 if let Err ( error) = conn. insert_benchmark_request ( & release_request) . await {
8491 log:: error!( "Failed to insert release benchmark request: {error}" ) ;
92+ } else {
93+ inserted = true ;
8594 }
8695 }
8796 }
88- Ok ( ( ) )
97+ Ok ( inserted )
8998}
9099
91100/// Sorts try and master requests that are in the `ArtifactsReady` status and return them in the
@@ -254,16 +263,20 @@ pub async fn enqueue_benchmark_request(
254263/// If there is a request that has artifacts ready, and nothing is currently in-progress,
255264/// it will be enqueued.
256265/// If there is a request whose jobs have all completed, it will be marked as completed.
266+ ///
267+ /// Returns benchmark requests that were completed.
257268async fn process_benchmark_requests (
258269 conn : & mut dyn database:: pool:: Connection ,
259- ) -> anyhow:: Result < ( ) > {
270+ ) -> anyhow:: Result < Vec < BenchmarkRequest > > {
260271 let queue = build_queue ( conn) . await ?;
261272
273+ let mut completed = vec ! [ ] ;
262274 for request in queue {
263275 match request. status ( ) {
264276 BenchmarkRequestStatus :: InProgress => {
265277 let tag = request. tag ( ) . expect ( "In progress request without a tag" ) ;
266278 if conn. maybe_mark_benchmark_request_as_completed ( tag) . await ? {
279+ completed. push ( request) ;
267280 continue ;
268281 }
269282 break ;
@@ -278,28 +291,89 @@ async fn process_benchmark_requests(
278291 }
279292 }
280293 }
281- Ok ( ( ) )
294+ Ok ( completed )
282295}
283296
284297/// For queueing jobs, add the jobs you want to queue to this function
285- async fn cron_enqueue_jobs ( site_ctxt : & SiteCtxt ) -> anyhow:: Result < ( ) > {
286- let mut conn = site_ctxt . conn ( ) . await ;
298+ async fn cron_enqueue_jobs ( ctxt : & SiteCtxt ) -> anyhow:: Result < ( ) > {
299+ let mut conn = ctxt . conn ( ) . await ;
287300
288- let index = conn . load_benchmark_request_index ( ) . await ? ;
301+ let index = ctxt . known_benchmark_requests . load ( ) ;
289302
303+ let mut requests_inserted = false ;
290304 // Put the master commits into the `benchmark_requests` queue
291- create_benchmark_request_master_commits ( site_ctxt , & * conn, & index) . await ?;
305+ requests_inserted |= create_benchmark_request_master_commits ( ctxt , & * conn, & index) . await ?;
292306 // Put the releases into the `benchmark_requests` queue
293- create_benchmark_request_releases ( & * conn, & index) . await ?;
307+ requests_inserted |= create_benchmark_request_releases ( & * conn, & index) . await ?;
294308 // Enqueue waiting requests and try to complete in-progress ones
295- process_benchmark_requests ( & mut * conn) . await ?;
309+ let completed_reqs = process_benchmark_requests ( & mut * conn) . await ?;
310+
311+ // If some change happened, reload the benchmark request index
312+ if requests_inserted {
313+ ctxt. known_benchmark_requests
314+ . store ( Arc :: new ( conn. load_benchmark_request_index ( ) . await ?) ) ;
315+ }
316+
317+ // Send a comment to GitHub for completed requests and reload the DB index
318+ if !completed_reqs. is_empty ( ) {
319+ let index = database:: Index :: load ( & mut * conn) . await ;
320+ log:: info!( "index has {} commits" , index. commits( ) . len( ) ) ;
321+ ctxt. index . store ( Arc :: new ( index) ) ;
322+
323+ // Refresh the landing page
324+ ctxt. landing_page . store ( Arc :: new ( None ) ) ;
325+
326+ // Send comments to GitHub
327+ for request in completed_reqs {
328+ let ( is_master, pr, sha, parent_sha) = match request. commit_type ( ) {
329+ BenchmarkRequestType :: Try {
330+ pr,
331+ parent_sha,
332+ sha,
333+ } => (
334+ false ,
335+ * pr,
336+ sha. clone ( ) . expect ( "Completed try commit without a SHA" ) ,
337+ parent_sha
338+ . clone ( )
339+ . expect ( "Completed try commit without a parent SHA" ) ,
340+ ) ,
341+ BenchmarkRequestType :: Master {
342+ pr,
343+ sha,
344+ parent_sha,
345+ } => ( true , * pr, sha. clone ( ) , parent_sha. clone ( ) ) ,
346+ BenchmarkRequestType :: Release { .. } => continue ,
347+ } ;
348+ let commit = QueuedCommit {
349+ pr,
350+ sha,
351+ parent_sha,
352+ include : None ,
353+ exclude : None ,
354+ runs : None ,
355+ commit_date : request. commit_date ( ) . map ( Date ) ,
356+ backends : Some (
357+ request
358+ . backends ( ) ?
359+ . into_iter ( )
360+ . map ( |b| b. as_str ( ) )
361+ . collect :: < Vec < _ > > ( )
362+ . join ( "," ) ,
363+ ) ,
364+ } ;
365+ post_comparison_comment ( ctxt, commit, is_master) . await ?;
366+ }
367+ }
296368
297369 Ok ( ( ) )
298370}
299371
300372/// Entry point for the cron job that manages the benchmark request and job queue.
301373pub async fn cron_main ( site_ctxt : Arc < RwLock < Option < Arc < SiteCtxt > > > > , run_interval : Duration ) {
302374 let mut interval = time:: interval ( run_interval) ;
375+ interval. set_missed_tick_behavior ( MissedTickBehavior :: Delay ) ;
376+
303377 let ctxt = site_ctxt. clone ( ) ;
304378
305379 loop {
0 commit comments