@@ -18,6 +18,7 @@ package handler
18
18
19
19
import (
20
20
"context"
21
+ "reflect"
21
22
"time"
22
23
23
24
"k8s.io/client-go/util/workqueue"
@@ -108,10 +109,40 @@ type TypedFuncs[object any, request comparable] struct {
108
109
GenericFunc func (context.Context , event.TypedGenericEvent [object ], workqueue.TypedRateLimitingInterface [request ])
109
110
}
110
111
112
+ func isPriorityQueue [request comparable ](q workqueue.TypedRateLimitingInterface [request ]) bool {
113
+ _ , ok := q .(priorityqueue.PriorityQueue [request ])
114
+ return ok
115
+ }
116
+
111
117
// Create implements EventHandler.
112
118
func (h TypedFuncs [object , request ]) Create (ctx context.Context , e event.TypedCreateEvent [object ], q workqueue.TypedRateLimitingInterface [request ]) {
113
119
if h .CreateFunc != nil {
114
- h .CreateFunc (ctx , e , q )
120
+ if ! reflect .TypeFor [object ]().Implements (reflect .TypeFor [client.Object ]()) || ! isPriorityQueue (q ) || isNil (e .Object ) {
121
+ h .CreateFunc (ctx , e , q )
122
+ return
123
+ }
124
+ wq := workqueueWithCustomAddFunc [request ]{
125
+ TypedRateLimitingInterface : q ,
126
+ // We already know that we have a priority queue, that event.Object implements
127
+ // client.Object and that its not nil
128
+ addFunc : func (item request , q workqueue.TypedRateLimitingInterface [request ]) {
129
+ // We construct a new event typed to client.Object because isObjectUnchanged
130
+ // is a generic and hence has to know at compile time the type of the event
131
+ // it gets. We only figure that out at runtime though, but we know for sure
132
+ // that it implements client.Object at this point so we can hardcode the event
133
+ // type to that.
134
+ evt := event.CreateEvent {Object : any (e .Object ).(client.Object )}
135
+ var priority int
136
+ if isObjectUnchanged (evt ) {
137
+ priority = LowPriority
138
+ }
139
+ q .(priorityqueue.PriorityQueue [request ]).AddWithOpts (
140
+ priorityqueue.AddOpts {Priority : priority },
141
+ item ,
142
+ )
143
+ },
144
+ }
145
+ h .CreateFunc (ctx , e , wq )
115
146
}
116
147
}
117
148
@@ -125,7 +156,27 @@ func (h TypedFuncs[object, request]) Delete(ctx context.Context, e event.TypedDe
125
156
// Update implements EventHandler.
126
157
func (h TypedFuncs [object , request ]) Update (ctx context.Context , e event.TypedUpdateEvent [object ], q workqueue.TypedRateLimitingInterface [request ]) {
127
158
if h .UpdateFunc != nil {
128
- h .UpdateFunc (ctx , e , q )
159
+ if ! reflect .TypeFor [object ]().Implements (reflect .TypeFor [client.Object ]()) || ! isPriorityQueue (q ) || isNil (e .ObjectOld ) || isNil (e .ObjectNew ) {
160
+ h .UpdateFunc (ctx , e , q )
161
+ return
162
+ }
163
+
164
+ wq := workqueueWithCustomAddFunc [request ]{
165
+ TypedRateLimitingInterface : q ,
166
+ // We already know that we have a priority queue, that event.ObjectOld and ObjectNew implement
167
+ // client.Object and that they are not nil
168
+ addFunc : func (item request , q workqueue.TypedRateLimitingInterface [request ]) {
169
+ var priority int
170
+ if any (e .ObjectOld ).(client.Object ).GetResourceVersion () == any (e .ObjectNew ).(client.Object ).GetResourceVersion () {
171
+ priority = LowPriority
172
+ }
173
+ q .(priorityqueue.PriorityQueue [request ]).AddWithOpts (
174
+ priorityqueue.AddOpts {Priority : priority },
175
+ item ,
176
+ )
177
+ },
178
+ }
179
+ h .UpdateFunc (ctx , e , wq )
129
180
}
130
181
}
131
182
@@ -142,25 +193,10 @@ const LowPriority = -100
142
193
// WithLowPriorityWhenUnchanged reduces the priority of events stemming from the initial listwatch or from a resync if
143
194
// and only if a priorityqueue.PriorityQueue is used. If not, it does nothing.
144
195
func WithLowPriorityWhenUnchanged [object client.Object , request comparable ](u TypedEventHandler [object , request ]) TypedEventHandler [object , request ] {
196
+ // TypedFuncs already implements this so just wrap
145
197
return TypedFuncs [object , request ]{
146
- CreateFunc : func (ctx context.Context , tce event.TypedCreateEvent [object ], trli workqueue.TypedRateLimitingInterface [request ]) {
147
- // Due to how the handlers are factored, we have to wrap the workqueue to be able
148
- // to inject custom behavior.
149
- u .Create (ctx , tce , workqueueWithCustomAddFunc [request ]{
150
- TypedRateLimitingInterface : trli ,
151
- addFunc : func (item request , q workqueue.TypedRateLimitingInterface [request ]) {
152
- addToQueueCreate (q , tce , item )
153
- },
154
- })
155
- },
156
- UpdateFunc : func (ctx context.Context , tue event.TypedUpdateEvent [object ], trli workqueue.TypedRateLimitingInterface [request ]) {
157
- u .Update (ctx , tue , workqueueWithCustomAddFunc [request ]{
158
- TypedRateLimitingInterface : trli ,
159
- addFunc : func (item request , q workqueue.TypedRateLimitingInterface [request ]) {
160
- addToQueueUpdate (q , tue , item )
161
- },
162
- })
163
- },
198
+ CreateFunc : u .Create ,
199
+ UpdateFunc : u .Update ,
164
200
DeleteFunc : u .Delete ,
165
201
GenericFunc : u .Generic ,
166
202
}
0 commit comments