Files
open-cluster-management/pkg/work/spoke/objectreader/options.go
Jian Qiu 63d9574ca2 Add watch-based feedback with dynamic informer lifecycle management (#1350)
* Add watch-based feedback with dynamic informer lifecycle management

Implements dynamic informer registration and cleanup for resources
configured with watch-based status feedback (FeedbackScrapeType=Watch).
This enables real-time status updates for watched resources while
efficiently managing resource lifecycle.

Features:
- Automatically register informers for resources with FeedbackWatchType
- Skip informer registration for FeedbackPollType or when not configured
- Clean up informers when resources are removed from manifestwork
- Clean up informers during applied manifestwork finalization
- Clean up informers when feedback type changes from watch to poll

Implementation:
- Refactored ObjectReader to interface for better modularity
- Added UnRegisterInformerFromAppliedManifestWork helper for bulk cleanup
- Enhanced AvailableStatusController to conditionally register informers
- Updated finalization controllers to unregister informers on cleanup
- Added nil safety checks to prevent panics during cleanup

Testing:
- Unit tests for informer registration based on feedback type
- Unit tests for bulk unregistration and nil safety
- Integration test for end-to-end watch-based feedback workflow
- Integration test for informer cleanup on manifestwork deletion
- All existing tests updated and passing

This feature improves performance by using watch-based updates for
real-time status feedback while maintaining efficient resource cleanup.

Signed-off-by: Jian Qiu <jqiu@redhat.com>

* Fallback to get from client when informer is not synced

Signed-off-by: Jian Qiu <jqiu@redhat.com>

---------

Signed-off-by: Jian Qiu <jqiu@redhat.com>
2026-01-29 06:46:21 +00:00

40 lines
1.0 KiB
Go

package objectreader
import (
"github.com/spf13/pflag"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/tools/cache"
workinformers "open-cluster-management.io/api/client/work/informers/externalversions/work/v1"
)
type Options struct {
MaxFeedbackWatch int32
}
func NewOptions() *Options {
return &Options{
MaxFeedbackWatch: 50,
}
}
func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.Int32Var(&o.MaxFeedbackWatch, "max-feedback-watch",
o.MaxFeedbackWatch, "The maximum number of watch for feedback results")
}
func (o *Options) NewObjectReader(dynamicClient dynamic.Interface, workInformer workinformers.ManifestWorkInformer) (ObjectReader, error) {
if err := workInformer.Informer().AddIndexers(map[string]cache.IndexFunc{
byWorkIndex: indexWorkByResource,
}); err != nil {
return nil, err
}
return &objectReader{
dynamicClient: dynamicClient,
informers: map[informerKey]*informerWithCancel{},
indexer: workInformer.Informer().GetIndexer(),
maxWatch: o.MaxFeedbackWatch,
}, nil
}