gitee.com/h79/goutils@v1.22.10/common/bus/bus.go (about) 1 package bus 2 3 import ( 4 "fmt" 5 "reflect" 6 "sync" 7 ) 8 9 var _ Publisher = (*Bus)(nil) 10 var _ Subscriber = (*Bus)(nil) 11 12 type eventHandler struct { 13 sync.Mutex // lock for an event handler - useful for running async callbacks serially 14 handle reflect.Value 15 fOnce bool //运行一次 16 async bool //异步处理 17 transactional bool //事务性 18 } 19 20 type Bus struct { 21 handlers map[string][]*eventHandler 22 rm sync.RWMutex 23 wg sync.WaitGroup 24 } 25 26 func New() *Bus { 27 return &Bus{ 28 handlers: make(map[string][]*eventHandler, 0), 29 rm: sync.RWMutex{}, 30 wg: sync.WaitGroup{}, 31 } 32 } 33 34 func (bus *Bus) doSubscribe(topic string, fn interface{}, handler *eventHandler) error { 35 bus.rm.Lock() 36 defer bus.rm.Unlock() 37 var kind = reflect.TypeOf(fn).Kind() 38 switch kind { 39 case reflect.Func: 40 case reflect.Chan: 41 if _, ok := fn.(EventChan); !ok { 42 return fmt.Errorf("%s is not of type EventChan", kind) 43 } 44 default: 45 return fmt.Errorf("%s is not of type reflect.Func or reflect.Chan", kind) 46 } 47 bus.handlers[topic] = append(bus.handlers[topic], handler) 48 return nil 49 } 50 51 func (bus *Bus) SubscribeEventChan(topic string, ch EventChan) error { 52 return bus.SubscribeEventChan(topic, ch) 53 } 54 55 func (bus *Bus) Subscribe(topic string, ch interface{}) error { 56 return bus.doSubscribe(topic, ch, &eventHandler{ 57 sync.Mutex{}, reflect.ValueOf(ch), false, false, false, 58 }) 59 } 60 61 func (bus *Bus) SubscribeAsync(topic string, fn interface{}, transactional bool) error { 62 return bus.doSubscribe(topic, fn, &eventHandler{ 63 sync.Mutex{}, reflect.ValueOf(fn), false, true, transactional, 64 }) 65 } 66 67 // SubscribeOnce subscribes to a topic once. Handler will be removed after executing. 68 // Returns error if `fn` is not a function. 69 func (bus *Bus) SubscribeOnce(topic string, fn interface{}) error { 70 return bus.doSubscribe(topic, fn, &eventHandler{ 71 sync.Mutex{}, reflect.ValueOf(fn), true, false, false, 72 }) 73 } 74 75 // SubscribeOnceAsync subscribes to a topic once with an asynchronous callback 76 // Async determines whether subsequent Publish should wait for callback return 77 // Handler will be removed after executing. 78 // Returns error if `fn` is not a function. 79 func (bus *Bus) SubscribeOnceAsync(topic string, fn interface{}) error { 80 return bus.doSubscribe(topic, fn, &eventHandler{ 81 sync.Mutex{}, reflect.ValueOf(fn), true, true, false, 82 }) 83 } 84 85 func (bus *Bus) UnSubscribe(topic string, ch interface{}) { 86 bus.rm.Lock() 87 defer bus.rm.Unlock() 88 handlers, found := bus.handlers[topic] 89 if !found || len(handlers) == 0 { 90 return 91 } 92 for i, c := range handlers { 93 if c.handle == reflect.ValueOf(ch) { 94 bus.handlers[topic] = append(handlers[:i], handlers[i+1:]...) 95 return 96 } 97 } 98 } 99 100 func (bus *Bus) Start() error { 101 return nil 102 } 103 104 func (bus *Bus) Stop() { 105 } 106 107 func (bus *Bus) PublishArgs(topic string, args ...interface{}) { 108 bus.rm.RLock() 109 hs, found := bus.handlers[topic] 110 if !found { 111 bus.rm.RUnlock() 112 return 113 } 114 handlers := append([]*eventHandler{}, hs...) 115 bus.rm.RUnlock() 116 for i, handler := range handlers { 117 if handler.fOnce { 118 bus.removeHandler(topic, i) 119 } 120 if !handler.async { //同步 121 bus.doPublish(handler, args...) 122 } else { 123 bus.wg.Add(1) 124 if handler.transactional { 125 handler.Lock() 126 } 127 go bus.doPublishAsync(handler, args...) 128 } 129 } 130 } 131 132 func (bus *Bus) Publish(topic string, ev Event) { 133 bus.PublishArgs(topic, ev) 134 } 135 136 func (bus *Bus) doPublish(eventHandle *eventHandler, args ...interface{}) { 137 var kind = eventHandle.handle.Kind() 138 switch kind { 139 case reflect.Func: 140 vs := make([]reflect.Value, 0) 141 for _, arg := range args { 142 vs = append(vs, reflect.ValueOf(arg)) 143 } 144 eventHandle.handle.Call(vs) 145 case reflect.Chan: 146 eventCh, ex := eventHandle.handle.Interface().(EventChan) 147 if !ex { 148 return 149 } 150 for i := range args { 151 if event, ok := args[i].(Event); ok { 152 eventCh <- event 153 } 154 } 155 default: 156 } 157 } 158 159 func (bus *Bus) doPublishAsync(handler *eventHandler, args ...interface{}) { 160 defer bus.wg.Done() 161 if handler.transactional { 162 defer handler.Unlock() 163 } 164 bus.doPublish(handler, args...) 165 } 166 167 func (bus *Bus) removeHandler(topic string, idx int) { 168 handlers, ok := bus.handlers[topic] 169 if !ok { 170 return 171 } 172 l := len(handlers) 173 174 if 0 > idx || idx >= l { 175 return 176 } 177 bus.handlers[topic] = append(handlers[:idx], handlers[idx+1:]...) 178 } 179 180 func (bus *Bus) Wait() { 181 bus.wg.Wait() 182 }