@@ -22,9 +22,9 @@ package kube
2222
2323import (
2424 "context"
25- "time"
2625
2726 "github.com/v3io/scaler/pkg/ingresscache"
27+ "github.com/v3io/scaler/pkg/scalertypes"
2828
2929 "github.com/nuclio/errors"
3030 "github.com/nuclio/logger"
@@ -35,29 +35,6 @@ import (
3535 "k8s.io/client-go/tools/cache"
3636)
3737
38- const (
39- defaultResyncInterval = 30 * time .Second
40- )
41-
42- // ResolveTargetsFromIngressCallback defines a function that extracts a list of target identifiers
43- // (e.g., names of services the Ingress routes traffic to) from a Kubernetes Ingress resource.
44- //
45- // This function is expected to be implemented externally and passed into the IngressWatcher,
46- // allowing for custom logic such as parsing annotations, labels, or other ingress metadata.
47- //
48- // Parameters:
49- // - ingress: The Kubernetes Ingress resource to extract targets from
50- //
51- // Returns:
52- // - []string: A slice of target identifiers (e.g., service names, endpoint addresses)
53- // - error: An error if target resolution fails
54- //
55- // Implementation guidelines:
56- // - Return a non-nil slice when targets are successfully resolved
57- // - Return a non-nil error if resolution fails
58- // - Should handle nil or malformed Ingress objects gracefully and return an error in such cases
59- type ResolveTargetsFromIngressCallback func (ingress * networkingv1.Ingress ) ([]string , error )
60-
6138type ingressValue struct {
6239 name string
6340 host string
@@ -68,31 +45,32 @@ type ingressValue struct {
6845// IngressWatcher watches for changes in Kubernetes Ingress resources and updates the ingress cache accordingly
6946type IngressWatcher struct {
7047 ctx context.Context
48+ cancel context.CancelFunc
7149 logger logger.Logger
7250 cache ingresscache.IngressHostCache
7351 factory informers.SharedInformerFactory
7452 informer cache.SharedIndexInformer
75- resolveTargetsCallback ResolveTargetsFromIngressCallback
53+ resolveTargetsCallback scalertypes. ResolveTargetsFromIngressCallback
7654}
7755
7856func NewIngressWatcher (
79- ctx context.Context ,
57+ dlxCtx context.Context ,
8058 dlxLogger logger.Logger ,
8159 kubeClient kubernetes.Interface ,
82- ingressCache ingresscache.IngressCache ,
83- resolveTargetsCallback ResolveTargetsFromIngressCallback ,
84- resyncTimeout * time.Duration ,
60+ resolveTargetsCallback scalertypes.ResolveTargetsFromIngressCallback ,
61+ resyncInterval scalertypes.Duration ,
8562 namespace string ,
8663 labelSelector string ,
8764) (* IngressWatcher , error ) {
88- if resyncTimeout == nil {
89- defaultTimeout := defaultResyncInterval
90- resyncTimeout = & defaultTimeout
65+ if resyncInterval .Duration == 0 {
66+ resyncInterval = scalertypes.Duration {Duration : scalertypes .DefaultResyncInterval }
9167 }
9268
69+ ctxWithCancel , cancel := context .WithCancel (dlxCtx )
70+
9371 factory := informers .NewSharedInformerFactoryWithOptions (
9472 kubeClient ,
95- * resyncTimeout ,
73+ resyncInterval . Duration ,
9674 informers .WithNamespace (namespace ),
9775 informers .WithTweakListOptions (func (options * metav1.ListOptions ) {
9876 options .LabelSelector = labelSelector
@@ -101,9 +79,10 @@ func NewIngressWatcher(
10179 ingressInformer := factory .Networking ().V1 ().Ingresses ().Informer ()
10280
10381 ingressWatcher := & IngressWatcher {
104- ctx : ctx ,
82+ ctx : ctxWithCancel ,
83+ cancel : cancel ,
10584 logger : dlxLogger .GetChild ("watcher" ),
106- cache : & ingressCache ,
85+ cache : ingresscache . NewIngressCache ( dlxLogger ) ,
10786 factory : factory ,
10887 informer : ingressInformer ,
10988 resolveTargetsCallback : resolveTargetsCallback ,
@@ -135,9 +114,15 @@ func (iw *IngressWatcher) Start() error {
135114
136115func (iw * IngressWatcher ) Stop () {
137116 iw .logger .Info ("Stopping ingress watcher" )
117+ iw .cancel ()
138118 iw .factory .Shutdown ()
139119}
140120
121+ // GetIngressHostCacheReader expose read-only access to the ingress cache
122+ func (iw * IngressWatcher ) GetIngressHostCacheReader () ingresscache.IngressHostCacheReader {
123+ return iw .cache
124+ }
125+
141126// --- ResourceEventHandler methods ---
142127
143128func (iw * IngressWatcher ) AddHandler (obj interface {}) {
@@ -167,6 +152,26 @@ func (iw *IngressWatcher) AddHandler(obj interface{}) {
167152}
168153
169154func (iw * IngressWatcher ) UpdateHandler (oldObj , newObj interface {}) {
155+ oldIngressResource , ok := oldObj .(* networkingv1.Ingress )
156+ if ! ok {
157+ iw .logger .DebugWith ("Failed to cast old object to Ingress" ,
158+ "object" , oldObj )
159+ return
160+ }
161+
162+ newIngressResource , ok := newObj .(* networkingv1.Ingress )
163+ if ! ok {
164+ iw .logger .DebugWith ("Failed to cast new object to Ingress" ,
165+ "object" , newObj )
166+ return
167+ }
168+
169+ // ResourceVersion is managed by Kubernetes and indicates whether the resource has changed.
170+ // Comparing resourceVersion helps avoid unnecessary updates triggered by periodic informer resync
171+ if oldIngressResource .ResourceVersion == newIngressResource .ResourceVersion {
172+ return
173+ }
174+
170175 oldIngress , err := iw .extractValuesFromIngressResource (oldObj )
171176 if err != nil {
172177 iw .logger .DebugWith ("Update ingress handler - failed to extract values from old object" ,
@@ -249,7 +254,7 @@ func (iw *IngressWatcher) extractValuesFromIngressResource(obj interface{}) (*in
249254
250255 targets , err := iw .resolveTargetsCallback (ingress )
251256 if err != nil {
252- return nil , errors .Wrap (err , "Failed to extract targets from ingress labels" )
257+ return nil , errors .Wrapf (err , "Failed to extract targets from ingress labels: %s" , err . Error () )
253258 }
254259
255260 if len (targets ) == 0 {
0 commit comments