1
1
mod utils;
2
2
3
+ use crate :: github:: comparison_summary:: post_comparison_comment;
3
4
use crate :: job_queue:: utils:: { parse_release_string, ExtractIf } ;
4
5
use crate :: load:: { partition_in_place, SiteCtxt } ;
5
6
use chrono:: Utc ;
6
7
use collector:: benchmark_set:: benchmark_set_count;
7
8
use database:: {
8
- BenchmarkRequest , BenchmarkRequestIndex , BenchmarkRequestStatus , PendingBenchmarkRequests ,
9
- Target ,
9
+ BenchmarkRequest , BenchmarkRequestIndex , BenchmarkRequestStatus , BenchmarkRequestType , Date ,
10
+ PendingBenchmarkRequests , QueuedCommit , Target ,
10
11
} ;
11
12
use parking_lot:: RwLock ;
12
13
use std:: { str:: FromStr , sync:: Arc } ;
13
- use tokio:: time:: { self , Duration } ;
14
+ use tokio:: time:: { self , Duration , MissedTickBehavior } ;
14
15
15
16
pub fn run_new_queue ( ) -> bool {
16
17
std:: env:: var ( "RUN_CRON" )
@@ -20,12 +21,13 @@ pub fn run_new_queue() -> bool {
20
21
}
21
22
22
23
/// 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.
24
26
async fn create_benchmark_request_master_commits (
25
27
ctxt : & SiteCtxt ,
26
28
conn : & dyn database:: pool:: Connection ,
27
29
index : & BenchmarkRequestIndex ,
28
- ) -> anyhow:: Result < ( ) > {
30
+ ) -> anyhow:: Result < bool > {
29
31
let now = Utc :: now ( ) ;
30
32
31
33
let master_commits = ctxt. get_master_commits ( ) ;
@@ -38,6 +40,7 @@ async fn create_benchmark_request_master_commits(
38
40
// TODO; delete at some point in the future
39
41
let cutoff: chrono:: DateTime < Utc > = chrono:: DateTime :: from_str ( "2025-08-27T00:00:00.000Z" ) ?;
40
42
43
+ let mut inserted = false ;
41
44
for master_commit in master_commits {
42
45
// We don't want to add masses of obsolete data
43
46
if master_commit. time >= cutoff && !index. contains_tag ( & master_commit. sha ) {
@@ -51,18 +54,21 @@ async fn create_benchmark_request_master_commits(
51
54
log:: info!( "Inserting master benchmark request {benchmark:?}" ) ;
52
55
if let Err ( error) = conn. insert_benchmark_request ( & benchmark) . await {
53
56
log:: error!( "Failed to insert master benchmark request: {error:?}" ) ;
57
+ } else {
58
+ inserted = true ;
54
59
}
55
60
}
56
61
}
57
- Ok ( ( ) )
62
+ Ok ( inserted )
58
63
}
59
64
60
65
/// Store the latest release commits or do nothing if all of them are
61
66
/// already in the database
67
+ /// Returns `true` if at least one benchmark request was inserted.
62
68
async fn create_benchmark_request_releases (
63
69
conn : & dyn database:: pool:: Connection ,
64
70
index : & BenchmarkRequestIndex ,
65
- ) -> anyhow:: Result < ( ) > {
71
+ ) -> anyhow:: Result < bool > {
66
72
let releases: String = reqwest:: get ( "https://static.rust-lang.org/manifests.txt" )
67
73
. await ?
68
74
. text ( )
@@ -76,16 +82,19 @@ async fn create_benchmark_request_releases(
76
82
. filter_map ( parse_release_string)
77
83
. take ( 20 ) ;
78
84
85
+ let mut inserted = false ;
79
86
for ( name, commit_date) in releases {
80
87
if commit_date >= cutoff && !index. contains_tag ( & name) {
81
88
let release_request = BenchmarkRequest :: create_release ( & name, commit_date) ;
82
89
log:: info!( "Inserting release benchmark request {release_request:?}" ) ;
83
90
if let Err ( error) = conn. insert_benchmark_request ( & release_request) . await {
84
91
log:: error!( "Failed to insert release benchmark request: {error}" ) ;
92
+ } else {
93
+ inserted = true ;
85
94
}
86
95
}
87
96
}
88
- Ok ( ( ) )
97
+ Ok ( inserted )
89
98
}
90
99
91
100
/// 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(
254
263
/// If there is a request that has artifacts ready, and nothing is currently in-progress,
255
264
/// it will be enqueued.
256
265
/// If there is a request whose jobs have all completed, it will be marked as completed.
266
+ ///
267
+ /// Returns benchmark requests that were completed.
257
268
async fn process_benchmark_requests (
258
269
conn : & mut dyn database:: pool:: Connection ,
259
- ) -> anyhow:: Result < ( ) > {
270
+ ) -> anyhow:: Result < Vec < BenchmarkRequest > > {
260
271
let queue = build_queue ( conn) . await ?;
261
272
273
+ let mut completed = vec ! [ ] ;
262
274
for request in queue {
263
275
match request. status ( ) {
264
276
BenchmarkRequestStatus :: InProgress => {
265
277
let tag = request. tag ( ) . expect ( "In progress request without a tag" ) ;
266
278
if conn. maybe_mark_benchmark_request_as_completed ( tag) . await ? {
279
+ completed. push ( request) ;
267
280
continue ;
268
281
}
269
282
break ;
@@ -278,28 +291,89 @@ async fn process_benchmark_requests(
278
291
}
279
292
}
280
293
}
281
- Ok ( ( ) )
294
+ Ok ( completed )
282
295
}
283
296
284
297
/// 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 ;
287
300
288
- let index = conn . load_benchmark_request_index ( ) . await ? ;
301
+ let index = ctxt . known_benchmark_requests . load ( ) ;
289
302
303
+ let mut requests_inserted = false ;
290
304
// 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 ?;
292
306
// 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 ?;
294
308
// 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
+ }
296
368
297
369
Ok ( ( ) )
298
370
}
299
371
300
372
/// Entry point for the cron job that manages the benchmark request and job queue.
301
373
pub async fn cron_main ( site_ctxt : Arc < RwLock < Option < Arc < SiteCtxt > > > > , run_interval : Duration ) {
302
374
let mut interval = time:: interval ( run_interval) ;
375
+ interval. set_missed_tick_behavior ( MissedTickBehavior :: Delay ) ;
376
+
303
377
let ctxt = site_ctxt. clone ( ) ;
304
378
305
379
loop {
0 commit comments