Skip to content

Commit d212757

Browse files
authored
refactor scheduler filters package (#797)
* refactor schdeuler filters package to simplify and improve readability and maintainability Signed-off-by: Nir Rozenbaum <[email protected]> * filter refactor finalizing Signed-off-by: Nir Rozenbaum <[email protected]> --------- Signed-off-by: Nir Rozenbaum <[email protected]>
1 parent cb52769 commit d212757

11 files changed

+544
-372
lines changed

pkg/epp/scheduling/config.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ package scheduling
1818

1919
import (
2020
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/plugins"
21-
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/plugins/filter"
22-
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/plugins/picker"
2321
)
2422

2523
// NewSchedulerConfig creates a new SchedulerConfig object with the given plugins.
@@ -42,15 +40,3 @@ type SchedulerConfig struct {
4240
picker plugins.Picker
4341
postSchedulePlugins []plugins.PostSchedule
4442
}
45-
46-
// When the scheduler is initialized with NewScheduler function, this config will be used as default.
47-
// it's possible to call NewSchedulerWithConfig to pass a different argument.
48-
49-
// For build time plugins changes, it's recommended to change the defaultConfig variable in this file.
50-
var defaultConfig = &SchedulerConfig{
51-
preSchedulePlugins: []plugins.PreSchedule{},
52-
filters: []plugins.Filter{&filter.SheddableRequestFilter{}, filter.LowLatencyFilter},
53-
scorers: map[plugins.Scorer]int{},
54-
picker: &picker.RandomPicker{},
55-
postSchedulePlugins: []plugins.PostSchedule{},
56-
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package filter
18+
19+
import (
20+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/plugins"
21+
"sigs.k8s.io/gateway-api-inference-extension/pkg/epp/scheduling/types"
22+
logutil "sigs.k8s.io/gateway-api-inference-extension/pkg/epp/util/logging"
23+
)
24+
25+
// DecisionTreeFilter applies current fitler, and then recursively applies next filters
26+
// depending success or failure of the current filter.
27+
// It can be used to construct a flow chart algorithm.
28+
type DecisionTreeFilter struct {
29+
Current plugins.Filter
30+
// NextOnSuccess filter will be applied after successfully applying the current filter.
31+
// The filtered results will be passed to the next filter.
32+
NextOnSuccess plugins.Filter
33+
// NextOnFailure filter will be applied if current filter results in no pods.
34+
// The original input will be passed to the next filter.
35+
NextOnFailure plugins.Filter
36+
// NextOnSuccessOrFailure is a convenience field to configure the next filter regardless of the
37+
// success or failure of the current filter.
38+
// NOTE: When using NextOnSuccessOrFailure, both nextOnSuccess and nextOnFailure SHOULD be nil.
39+
// However if that's not the case, nextOnSuccess and nextOnFailure will be used, instead of
40+
// NextOnSuccessOrFailure, in the success and failure scenarios, respectively.
41+
NextOnSuccessOrFailure plugins.Filter
42+
}
43+
44+
// Name returns the name of the filter.
45+
func (f *DecisionTreeFilter) Name() string {
46+
if f == nil {
47+
return "nil"
48+
}
49+
return f.Current.Name()
50+
}
51+
52+
// Filter filters out pods that doesn't meet the filter criteria.
53+
func (f *DecisionTreeFilter) Filter(ctx *types.SchedulingContext, pods []types.Pod) []types.Pod {
54+
loggerTrace := ctx.Logger.V(logutil.TRACE)
55+
filteredPod := f.Current.Filter(ctx, pods)
56+
57+
next := f.NextOnSuccessOrFailure
58+
if len(filteredPod) > 0 {
59+
if f.NextOnSuccess == nil && f.NextOnSuccessOrFailure == nil {
60+
// No succeeding filters to run, return.
61+
return filteredPod
62+
}
63+
if f.NextOnSuccess != nil {
64+
next = f.NextOnSuccess
65+
}
66+
loggerTrace.Info("Filter succeeded", "filter", f.Name(), "next", next.Name(), "filteredPodCount", len(filteredPod))
67+
// On success, pass the filtered result to the next filter.
68+
return next.Filter(ctx, filteredPod)
69+
} else {
70+
if f.NextOnFailure == nil && f.NextOnSuccessOrFailure == nil {
71+
// No succeeding filters to run, return.
72+
return filteredPod
73+
}
74+
if f.NextOnFailure != nil {
75+
next = f.NextOnFailure
76+
}
77+
loggerTrace.Info("Filter failed", "filter", f.Name(), "next", next.Name())
78+
// On failure, pass the initial set of pods to the next filter.
79+
return next.Filter(ctx, pods)
80+
}
81+
}

0 commit comments

Comments
 (0)