Skip to content

Commit 9ba0f9b

Browse files
authored
Merge pull request #1653 from ricardomaraschini/new-classifier
feat: move classifier to its own package
2 parents 89535b9 + 95a631f commit 9ba0f9b

File tree

6 files changed

+1240
-73
lines changed

6 files changed

+1240
-73
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package classifier
17+
18+
// Classifier is a function that classifies a resource usage based on a limit.
19+
// The function should return true if the resource usage matches the classifier
20+
// intent.
21+
type Classifier[K comparable, V any] func(K, V, V) bool
22+
23+
// Comparer is a function that compares two objects. This function should return
24+
// -1 if the first object is less than the second, 0 if they are equal, and 1 if
25+
// the first object is greater than the second. Of course this is a simplification
26+
// and any value between -1 and 1 can be returned.
27+
type Comparer[V any] func(V, V) int
28+
29+
// Values is a map of values indexed by a comparable key. An example of this
30+
// can be a list of resources indexed by a node name.
31+
type Values[K comparable, V any] map[K]V
32+
33+
// Limits is a map of list of limits indexed by a comparable key. Each limit
34+
// inside the list requires a classifier to evaluate.
35+
type Limits[K comparable, V any] map[K][]V
36+
37+
// Classify is a function that classifies based on classifier functions. This
38+
// function receives Values, a list of n Limits (indexed by name), and a list
39+
// of n Classifiers. The classifier at n position is called to evaluate the
40+
// limit at n position. The first classifier to return true will receive the
41+
// value, at this point the loop will break and the next value will be
42+
// evaluated. This function returns a slice of maps, each position in the
43+
// returned slice correspond to one of the classifiers (e.g. if n limits
44+
// and classifiers are provided, the returned slice will have n maps).
45+
func Classify[K comparable, V any](
46+
values Values[K, V], limits Limits[K, V], classifiers ...Classifier[K, V],
47+
) []map[K]V {
48+
result := make([]map[K]V, len(classifiers))
49+
for i := range classifiers {
50+
result[i] = make(map[K]V)
51+
}
52+
53+
for index, usage := range values {
54+
for i, limit := range limits[index] {
55+
if len(classifiers) <= i {
56+
continue
57+
}
58+
if !classifiers[i](index, usage, limit) {
59+
continue
60+
}
61+
result[i][index] = usage
62+
break
63+
}
64+
}
65+
66+
return result
67+
}
68+
69+
// ForMap is a function that returns a classifier that compares all values in a
70+
// map. The function receives a Comparer function that is used to compare all
71+
// the map values. The returned Classifier will return true only if the
72+
// provided Comparer function returns a value less than 0 for all the values.
73+
func ForMap[K, I comparable, V any, M ~map[I]V](cmp Comparer[V]) Classifier[K, M] {
74+
return func(_ K, usages, limits M) bool {
75+
for idx, usage := range usages {
76+
if limit, ok := limits[idx]; ok {
77+
if cmp(usage, limit) >= 0 {
78+
return false
79+
}
80+
}
81+
}
82+
return true
83+
}
84+
}

0 commit comments

Comments
 (0)