@@ -105,6 +105,7 @@ async fn create_benchmark_request_releases(
105105/// correct queue order, where the first returned request will be the first to be benchmarked next.
106106/// Doesn't consider in-progress requests or release artifacts.
107107fn sort_benchmark_requests ( pending : PendingBenchmarkRequests ) -> Vec < BenchmarkRequest > {
108+ log:: debug!( "Sorting benchmark requests. Pending requests: {pending:?}" ) ;
108109 let PendingBenchmarkRequests {
109110 requests : mut pending,
110111 completed_parent_tags : mut done,
@@ -162,6 +163,7 @@ fn sort_benchmark_requests(pending: PendingBenchmarkRequests) -> Vec<BenchmarkRe
162163 }
163164 finished += level_len;
164165 }
166+ log:: debug!( "Sorted pending requests: {pending:?}" ) ;
165167 pending
166168}
167169
@@ -189,9 +191,24 @@ pub async fn build_queue(
189191 matches ! ( request. status( ) , BenchmarkRequestStatus :: InProgress )
190192 } ) ;
191193
192- // We sort the in-progress ones based on the started date
194+ // We sort the in-progress ones based on their created date
193195 queue. sort_unstable_by_key ( |req| req. created_at ( ) ) ;
194196
197+ // Treat in-progress requests as completed for the purposes of sorting.
198+ // Otherwise, if no requests in `pending` have a completed parent, queue sorting would
199+ // end in an error due to no parents being ready.
200+ // This can happen if all pending requests have a parent that is either also pending or
201+ // in-progress, but not completed.
202+ //
203+ // This also allows us to make the queue more stable, because the "future order" will be based
204+ // on what will happen once the currently in-progress request finishes.
205+ for in_progress in & queue {
206+ let tag = in_progress
207+ . tag ( )
208+ . expect ( "In progress request without a tag" ) ;
209+ pending. completed_parent_tags . insert ( tag. to_string ( ) ) ;
210+ }
211+
195212 // Add release artifacts ordered by the release tag (1.87.0 before 1.88.0) and `created_at`.
196213 let mut release_artifacts: Vec < BenchmarkRequest > = pending
197214 . requests
@@ -575,6 +592,7 @@ mod tests {
575592 use crate :: job_queue:: { build_queue, process_benchmark_requests} ;
576593 use chrono:: Utc ;
577594 use database:: pool:: JobEnqueueResult ;
595+ use database:: tests:: builder:: CollectorBuilder ;
578596 use database:: tests:: run_postgres_test;
579597 use database:: {
580598 BenchmarkJobConclusion , BenchmarkJobKind , BenchmarkRequest , BenchmarkRequestStatus ,
@@ -771,6 +789,39 @@ mod tests {
771789 . await ;
772790 }
773791
792+ /// Make sure that queue ordering still works even when all pending requests have a parent
793+ /// that is either also pending or in-progress.
794+ #[ tokio:: test]
795+ async fn queue_ordering_deps_in_queue ( ) {
796+ run_postgres_test ( |mut ctx| async {
797+ ctx. add_collector ( CollectorBuilder :: default ( ) ) . await ;
798+
799+ ctx. insert_master_request ( "parent" , "parent2" , 1 ) . await ;
800+ ctx. complete_request ( "parent" ) . await ;
801+
802+ // In progress
803+ ctx. insert_master_request ( "1f88" , "parent" , 148446 ) . await ;
804+ process_benchmark_requests ( ctx. db_mut ( ) , & mut vec ! [ ] ) . await ?;
805+
806+ // Artifacts ready
807+ ctx. insert_master_request ( "5f9d" , "2038" , 148456 ) . await ;
808+ ctx. insert_master_request ( "90b6" , "5f9d" , 148462 ) . await ;
809+ ctx. insert_try_request ( 112049 ) . await ;
810+
811+ let db = ctx. db ( ) ;
812+ assert ! ( db
813+ . attach_shas_to_try_benchmark_request( 112049 , "60ce" , "1f88" , Utc :: now( ) )
814+ . await
815+ . unwrap( ) ) ;
816+ ctx. insert_master_request ( "2038" , "1f88" , 148350 ) . await ;
817+
818+ let queue = build_queue ( db) . await ?;
819+ queue_order_matches ( & queue, & [ "1f88" , "60ce" , "2038" , "5f9d" , "90b6" ] ) ;
820+ Ok ( ctx)
821+ } )
822+ . await ;
823+ }
824+
774825 #[ tokio:: test]
775826 async fn insert_all_jobs ( ) {
776827 run_postgres_test ( |mut ctx| async {
0 commit comments