@@ -20,6 +20,7 @@ import (
2020 "context"
2121 "encoding/json"
2222 "fmt"
23+ "sort"
2324
2425 "sigs.k8s.io/controller-runtime/pkg/log"
2526 "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/plugins"
@@ -36,53 +37,65 @@ const (
3637var _ framework.Picker = & MaxScorePicker {}
3738
3839// MaxScorePickerFactory defines the factory function for MaxScorePicker.
39- func MaxScorePickerFactory (name string , _ json.RawMessage , _ plugins.Handle ) (plugins.Plugin , error ) {
40- return NewMaxScorePicker ().WithName (name ), nil
40+ func MaxScorePickerFactory (name string , rawParameters json.RawMessage , _ plugins.Handle ) (plugins.Plugin , error ) {
41+ parameters := pickerParameters {MaxNumOfEndpoints : DefaultMaxNumOfEndpoints }
42+ if rawParameters != nil {
43+ if err := json .Unmarshal (rawParameters , & parameters ); err != nil {
44+ return nil , fmt .Errorf ("failed to parse the parameters of the '%s' picker - %w" , MaxScorePickerType , err )
45+ }
46+ }
47+
48+ return NewMaxScorePicker (parameters .MaxNumOfEndpoints ).WithName (name ), nil
4149}
4250
4351// NewMaxScorePicker initializes a new MaxScorePicker and returns its pointer.
44- func NewMaxScorePicker () * MaxScorePicker {
52+ func NewMaxScorePicker (maxNumOfEndpoints int ) * MaxScorePicker {
53+ if maxNumOfEndpoints <= 0 {
54+ maxNumOfEndpoints = DefaultMaxNumOfEndpoints // on invalid configuration value, fallback to default value
55+ }
56+
4557 return & MaxScorePicker {
46- tn : plugins.TypedName {Type : MaxScorePickerType , Name : MaxScorePickerType },
47- random : NewRandomPicker () ,
58+ typedName : plugins.TypedName {Type : MaxScorePickerType , Name : MaxScorePickerType },
59+ maxNumOfEndpoints : maxNumOfEndpoints ,
4860 }
4961}
5062
51- // MaxScorePicker picks the pod with the maximum score from the list of candidates.
63+ // MaxScorePicker picks pod(s) with the maximum score from the list of candidates.
5264type MaxScorePicker struct {
53- tn plugins.TypedName
54- random * RandomPicker
55- }
56-
57- // TypedName returns the type and name tuple of this plugin instance.
58- func (p * MaxScorePicker ) TypedName () plugins.TypedName {
59- return p .tn
65+ typedName plugins.TypedName
66+ maxNumOfEndpoints int // maximum number of endpoints to pick
6067}
6168
6269// WithName sets the picker's name
6370func (p * MaxScorePicker ) WithName (name string ) * MaxScorePicker {
64- p .tn .Name = name
71+ p .typedName .Name = name
6572 return p
6673}
6774
75+ // TypedName returns the type and name tuple of this plugin instance.
76+ func (p * MaxScorePicker ) TypedName () plugins.TypedName {
77+ return p .typedName
78+ }
79+
6880// Pick selects the pod with the maximum score from the list of candidates.
6981func (p * MaxScorePicker ) Pick (ctx context.Context , cycleState * types.CycleState , scoredPods []* types.ScoredPod ) * types.ProfileRunResult {
70- log .FromContext (ctx ).V (logutil .DEBUG ).Info (fmt .Sprintf ("Selecting a pod with the max score from %d candidates: %+v" , len (scoredPods ), scoredPods ))
71-
72- highestScorePods := []* types.ScoredPod {}
73- maxScore := - 1.0 // pods min score is 0, putting value lower than 0 in order to find at least one pod as highest
74- for _ , pod := range scoredPods {
75- if pod .Score > maxScore {
76- maxScore = pod .Score
77- highestScorePods = []* types.ScoredPod {pod }
78- } else if pod .Score == maxScore {
79- highestScorePods = append (highestScorePods , pod )
80- }
82+ log .FromContext (ctx ).V (logutil .DEBUG ).Info (fmt .Sprintf ("Selecting maximum '%d' pods from %d candidates sorted by max score: %+v" , p .maxNumOfEndpoints ,
83+ len (scoredPods ), scoredPods ))
84+
85+ sort .Slice (scoredPods , func (i , j int ) bool { // highest score first
86+ return scoredPods [i ].Score > scoredPods [j ].Score
87+ })
88+
89+ // if we have enough pods to return keep only the "maxNumOfEndpoints" highest scored pods
90+ if p .maxNumOfEndpoints < len (scoredPods ) {
91+ scoredPods = scoredPods [:p .maxNumOfEndpoints ]
8192 }
8293
83- if len (highestScorePods ) > 1 {
84- return p .random .Pick (ctx , cycleState , highestScorePods ) // pick randomly from the highest score pods
94+ targetPods := make ([]types.Pod , len (scoredPods ))
95+ for i , scoredPod := range scoredPods {
96+ targetPods [i ] = scoredPod
8597 }
8698
87- return & types.ProfileRunResult {TargetPod : highestScorePods [0 ]}
99+ return & types.ProfileRunResult {TargetPods : targetPods }
100+
88101}
0 commit comments