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  }