github.com/argoproj/argo-cd@v1.8.7/server/application/broadcaster.go (about) 1 package application 2 3 import ( 4 "sync" 5 6 log "github.com/sirupsen/logrus" 7 "k8s.io/apimachinery/pkg/watch" 8 9 appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1" 10 ) 11 12 type subscriber struct { 13 ch chan *appv1.ApplicationWatchEvent 14 filters []func(*appv1.ApplicationWatchEvent) bool 15 } 16 17 func (s *subscriber) matches(event *appv1.ApplicationWatchEvent) bool { 18 for i := range s.filters { 19 if !s.filters[i](event) { 20 return false 21 } 22 } 23 return true 24 } 25 26 type broadcasterHandler struct { 27 lock sync.Mutex 28 subscribers []*subscriber 29 } 30 31 func (b *broadcasterHandler) notify(event *appv1.ApplicationWatchEvent) { 32 // Make a local copy of b.subscribers, then send channel events outside the lock, 33 // to avoid data race on b.subscribers changes 34 subscribers := []*subscriber{} 35 b.lock.Lock() 36 subscribers = append(subscribers, b.subscribers...) 37 b.lock.Unlock() 38 39 for _, s := range subscribers { 40 if s.matches(event) { 41 select { 42 case s.ch <- event: 43 default: 44 // drop event if cannot send right away 45 log.WithField("application", event.Application.Name).Warn("unable to send event notification") 46 } 47 } 48 } 49 } 50 51 // Subscribe forward application informer watch events to the provided channel. 52 // The watch events are dropped if no receives are reading events from the channel so the channel must have 53 // buffer if dropping events is not acceptable. 54 func (b *broadcasterHandler) Subscribe(ch chan *appv1.ApplicationWatchEvent, filters ...func(event *appv1.ApplicationWatchEvent) bool) func() { 55 b.lock.Lock() 56 defer b.lock.Unlock() 57 subscriber := &subscriber{ch, filters} 58 b.subscribers = append(b.subscribers, subscriber) 59 return func() { 60 b.lock.Lock() 61 defer b.lock.Unlock() 62 for i := range b.subscribers { 63 if b.subscribers[i] == subscriber { 64 b.subscribers = append(b.subscribers[:i], b.subscribers[i+1:]...) 65 break 66 } 67 } 68 } 69 } 70 71 func (b *broadcasterHandler) OnAdd(obj interface{}) { 72 if app, ok := obj.(*appv1.Application); ok { 73 b.notify(&appv1.ApplicationWatchEvent{Application: *app, Type: watch.Added}) 74 } 75 } 76 77 func (b *broadcasterHandler) OnUpdate(_, newObj interface{}) { 78 if app, ok := newObj.(*appv1.Application); ok { 79 b.notify(&appv1.ApplicationWatchEvent{Application: *app, Type: watch.Modified}) 80 } 81 } 82 83 func (b *broadcasterHandler) OnDelete(obj interface{}) { 84 if app, ok := obj.(*appv1.Application); ok { 85 b.notify(&appv1.ApplicationWatchEvent{Application: *app, Type: watch.Deleted}) 86 } 87 }