github.com/quantosnetwork/Quantos@v0.0.0-20220306172517-e20b28c5a29a/events/listener.go (about) 1 package events 2 3 import ( 4 "fmt" 5 "github.com/fsnotify/fsnotify" 6 "github.com/quantosnetwork/Quantos/events/set" 7 "sync" 8 "time" 9 ) 10 11 // Listener is the function type to run on events. 12 type Listener func(interface{}) 13 14 type Subscribers map[string]Listener 15 16 type Observer struct { 17 quit chan bool 18 events chan *Event 19 watcher *fsnotify.Watcher 20 watchPatterns set.Set 21 watchDirs set.Set 22 listeners []Listener 23 mutex *sync.Mutex 24 bufferEvents []*Event 25 bufferDuration time.Duration 26 Verbose bool 27 } 28 29 // Open the observer channles and run the event loop, 30 // it will return an error if event loop already running. 31 func (o *Observer) Open() error { 32 // Check for mutex 33 if o.mutex == nil { 34 o.mutex = &sync.Mutex{} 35 } 36 37 if o.events != nil { 38 return fmt.Errorf("Observer already inititated.") 39 } 40 41 // Create the observer channels. 42 o.quit = make(chan bool) 43 o.events = make(chan *Event) 44 45 // Run the observer. 46 return o.eventLoop() 47 } 48 49 // Close the observer channles, 50 // it will return an error if close fails. 51 func (o *Observer) Close() error { 52 // Close event loop 53 if o.events != nil { 54 // Send a quit signal. 55 o.quit <- true 56 57 // Close channels. 58 close(o.quit) 59 close(o.events) 60 } 61 62 // Close file watcher. 63 if o.watcher != nil { 64 o.watcher.Close() 65 } 66 67 return nil 68 } 69 70 // AddListener adds a listener function to run on event, 71 // the listener function will recive the event object as argument. 72 func (o *Observer) AddListener(l Listener) { 73 // Check for mutex 74 if o.mutex == nil { 75 o.mutex = &sync.Mutex{} 76 } 77 78 // Lock: 79 // 1. operations on array listeners 80 o.mutex.Lock() 81 defer o.mutex.Unlock() 82 83 o.listeners = append(o.listeners, l) 84 } 85 86 // Emit an event, and event can be of any type, when event is triggered all 87 // listeners will be called using the event object. 88 func (o *Observer) Emit(event *Event) { 89 o.events <- event 90 } 91 92 // eventLoop runs the event loop. 93 func (o *Observer) eventLoop() error { 94 // Run observer. 95 go func() { 96 for { 97 select { 98 case event := <-o.events: 99 o.handleEvent(event) 100 case <-o.quit: 101 return 102 } 103 } 104 }() 105 106 return nil 107 } 108 109 func (o *Observer) handleEvent(event *Event) { 110 o.mutex.Lock() 111 defer o.mutex.Unlock() 112 // If we do not buffer events, just send this event now. 113 if o.bufferDuration == 0 { 114 o.sendEvent(event) 115 return 116 } 117 o.bufferEvents = append(o.bufferEvents, event) 118 // If this is the first event, set a timeout function. 119 if len(o.bufferEvents) == 1 { 120 time.AfterFunc(o.bufferDuration, func() { 121 // Lock: 122 // 1. operations on listeners array (sendEvent). 123 // 2. operations on bufferEvents array. 124 o.mutex.Lock() 125 defer o.mutex.Unlock() 126 127 // Send all events in event buffer. 128 for i := range o.bufferEvents { 129 o.sendEvent(o.bufferEvents[i]) 130 } 131 132 // Reset events buffer. 133 o.bufferEvents = make([]*Event, 0) 134 }) 135 } 136 } 137 138 var listeners Subscribers 139 140 func (o *Observer) sendEvent(event *Event) { 141 if event.Subscribable() { 142 subscribers := event.subscribers 143 for s := range subscribers { 144 go listeners[s](event) 145 } 146 } 147 }