@@ -26,6 +26,7 @@ use scheduling_logic_model::{IndexerOrd, SourceOrd};
2626use tracing:: { error, warn} ;
2727
2828use crate :: indexing_plan:: PhysicalIndexingPlan ;
29+ use crate :: indexing_scheduler:: MAX_LOAD_PER_PIPELINE ;
2930use crate :: indexing_scheduler:: scheduling:: scheduling_logic_model:: {
3031 IndexerAssignment , SchedulingProblem , SchedulingSolution ,
3132} ;
@@ -44,9 +45,6 @@ use crate::model::ShardLocations;
4445/// of 30%. Which translates into an overall load of 60%.
4546const CPU_PER_PIPELINE_LOAD_LOWER_THRESHOLD : CpuCapacity = CpuCapacity :: from_cpu_millis ( 1_200 ) ;
4647
47- /// That's 80% of a period
48- const MAX_LOAD_PER_PIPELINE : CpuCapacity = CpuCapacity :: from_cpu_millis ( 3_200 ) ;
49-
5048fn populate_problem (
5149 source : & SourceToSchedule ,
5250 problem : & mut SchedulingProblem ,
@@ -757,8 +755,8 @@ mod tests {
757755 convert_scheduling_solution_to_physical_plan_single_node_single_source,
758756 } ;
759757 use crate :: indexing_plan:: PhysicalIndexingPlan ;
760- use crate :: indexing_scheduler:: get_shard_locality_metrics;
761758 use crate :: indexing_scheduler:: scheduling:: assign_shards;
759+ use crate :: indexing_scheduler:: { MAX_LOAD_PER_PIPELINE , get_shard_locality_metrics} ;
762760 use crate :: model:: ShardLocations ;
763761
764762 fn source_id ( ) -> SourceUid {
@@ -939,6 +937,68 @@ mod tests {
939937 }
940938 }
941939
940+ #[ test]
941+ fn test_build_physical_plan_with_pipeline_limit ( ) {
942+ let indexer1 = "indexer1" . to_string ( ) ;
943+ let indexer2 = "indexer2" . to_string ( ) ;
944+ let source_uid0 = source_id ( ) ;
945+ let source_uid1 = source_id ( ) ;
946+ let source_0 = SourceToSchedule {
947+ source_uid : source_uid0. clone ( ) ,
948+ source_type : SourceToScheduleType :: Sharded {
949+ shard_ids : ( 0 ..16 ) . map ( ShardId :: from) . collect ( ) ,
950+ load_per_shard : NonZeroU32 :: new ( 800 ) . unwrap ( ) ,
951+ } ,
952+ params_fingerprint : 0 ,
953+ } ;
954+ let source_1 = SourceToSchedule {
955+ source_uid : source_uid1. clone ( ) ,
956+ source_type : SourceToScheduleType :: NonSharded {
957+ num_pipelines : 4 ,
958+ load_per_pipeline : NonZeroU32 :: new ( MAX_LOAD_PER_PIPELINE . cpu_millis ( ) ) . unwrap ( ) ,
959+ } ,
960+ params_fingerprint : 0 ,
961+ } ;
962+ let mut indexer_id_to_cpu_capacities = FnvHashMap :: default ( ) ;
963+ indexer_id_to_cpu_capacities. insert ( indexer1. clone ( ) , mcpu ( 16_000 ) ) ;
964+ indexer_id_to_cpu_capacities. insert ( indexer2. clone ( ) , mcpu ( 16_000 ) ) ;
965+ let shard_locations = ShardLocations :: default ( ) ;
966+ let indexing_plan = build_physical_indexing_plan (
967+ & [ source_0, source_1] ,
968+ & indexer_id_to_cpu_capacities,
969+ None ,
970+ & shard_locations,
971+ ) ;
972+ assert_eq ! ( indexing_plan. indexing_tasks_per_indexer( ) . len( ) , 2 ) ;
973+
974+ let node1_plan = indexing_plan. indexer ( & indexer1) . unwrap ( ) ;
975+ let node2_plan = indexing_plan. indexer ( & indexer2) . unwrap ( ) ;
976+
977+ let source_0_on_node1 = node1_plan
978+ . iter ( )
979+ . filter ( |task| task. source_id == source_uid0. source_id )
980+ . count ( ) ;
981+ let source_0_on_node2 = node2_plan
982+ . iter ( )
983+ . filter ( |task| task. source_id == source_uid0. source_id )
984+ . count ( ) ;
985+ assert ! ( source_0_on_node1 <= 3 ) ;
986+ assert ! ( source_0_on_node2 <= 3 ) ;
987+ assert_eq ! ( source_0_on_node1 + source_0_on_node2, 4 ) ;
988+
989+ let source_1_on_node1 = node1_plan
990+ . iter ( )
991+ . filter ( |task| task. source_id == source_uid1. source_id )
992+ . count ( ) ;
993+ let source_1_on_node2 = node2_plan
994+ . iter ( )
995+ . filter ( |task| task. source_id == source_uid1. source_id )
996+ . count ( ) ;
997+ assert ! ( source_1_on_node1 <= 3 ) ;
998+ assert ! ( source_1_on_node2 <= 3 ) ;
999+ assert_eq ! ( source_1_on_node1 + source_1_on_node2, 4 ) ;
1000+ }
1001+
9421002 fn make_indexing_tasks (
9431003 source_uid : & SourceUid ,
9441004 shards : & [ ( PipelineUid , & [ ShardId ] ) ] ,
0 commit comments