github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/notifier.go (about) 1 package db 2 3 import "time" 4 5 //go:generate counterfeiter . Notifier 6 7 type Notifier interface { 8 Notify() <-chan struct{} 9 Close() error 10 } 11 12 func newConditionNotifier(bus NotificationsBus, channel string, cond func() (bool, error)) (Notifier, error) { 13 notified, err := bus.Listen(channel) 14 if err != nil { 15 return nil, err 16 } 17 18 notifier := &conditionNotifier{ 19 cond: cond, 20 bus: bus, 21 channel: channel, 22 23 notified: notified, 24 notify: make(chan struct{}, 1), 25 26 stop: make(chan struct{}), 27 } 28 29 go notifier.watch() 30 31 return notifier, nil 32 } 33 34 type conditionNotifier struct { 35 cond func() (bool, error) 36 37 bus NotificationsBus 38 channel string 39 40 notified chan bool 41 notify chan struct{} 42 43 stop chan struct{} 44 } 45 46 func (notifier *conditionNotifier) Notify() <-chan struct{} { 47 return notifier.notify 48 } 49 50 func (notifier *conditionNotifier) Close() error { 51 close(notifier.stop) 52 return notifier.bus.Unlisten(notifier.channel, notifier.notified) 53 } 54 55 func (notifier *conditionNotifier) watch() { 56 for { 57 c, err := notifier.cond() 58 if err != nil { 59 select { 60 case <-time.After(5 * time.Second): 61 continue 62 case <-notifier.stop: 63 return 64 } 65 } 66 67 if c { 68 notifier.sendNotification() 69 } 70 71 dance: 72 for { 73 select { 74 case <-notifier.stop: 75 return 76 case ok := <-notifier.notified: 77 if ok { 78 notifier.sendNotification() 79 } else { 80 break dance 81 } 82 } 83 } 84 } 85 } 86 87 func (notifier *conditionNotifier) sendNotification() { 88 select { 89 case notifier.notify <- struct{}{}: 90 default: 91 } 92 }