Added TryFire
This allows handlers to return errors which will be returned to the caller. Also replaced error returned from On with a panic.
This commit is contained in:
parent
a2269cd439
commit
91d1562e0e
28
bus.go
28
bus.go
|
@ -8,7 +8,7 @@ func New() *Bus {
|
||||||
return &Bus{topics: make(map[string]*topic)}
|
return &Bus{topics: make(map[string]*topic)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Bus) On(event string, receiver interface{}) error {
|
func (d *Bus) On(event string, receiver interface{}) {
|
||||||
// TODO: make thread safe
|
// TODO: make thread safe
|
||||||
t, hasTopic := d.topics[event]
|
t, hasTopic := d.topics[event]
|
||||||
if !hasTopic {
|
if !hasTopic {
|
||||||
|
@ -18,25 +18,41 @@ func (d *Bus) On(event string, receiver interface{}) error {
|
||||||
|
|
||||||
sub, err := newSubscriptionFromFunc(receiver)
|
sub, err := newSubscriptionFromFunc(receiver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.addSubscriber(sub)
|
t.addSubscriber(sub)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Bus) Fire(event string, args ...interface{}) {
|
func (d *Bus) Fire(event string, args ...interface{}) {
|
||||||
|
_ = d.TryFire(event, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Bus) TryFire(event string, args ...interface{}) error {
|
||||||
// TODO: make thead safe
|
// TODO: make thead safe
|
||||||
topic, hasTopic := d.topics[event]
|
topic, hasTopic := d.topics[event]
|
||||||
if !hasTopic {
|
if !hasTopic {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
preparedArgs := prepareArgs(args)
|
preparedArgs := prepareArgs(args)
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
|
||||||
for sub := topic.head; sub != nil; sub = sub.next {
|
for sub := topic.head; sub != nil; sub = sub.next {
|
||||||
sub.handler.invoke(preparedArgs)
|
err := sub.handler.invoke(preparedArgs)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch len(errs) {
|
||||||
|
case 0:
|
||||||
|
return nil
|
||||||
|
case 1:
|
||||||
|
return errs[0]
|
||||||
|
}
|
||||||
|
return HandlerError{topic: event, errs: errs}
|
||||||
}
|
}
|
||||||
|
|
||||||
type topic struct {
|
type topic struct {
|
||||||
|
@ -65,4 +81,4 @@ func newSubscriptionFromFunc(fn interface{}) (*subscription, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &subscription{handler: handler, next: nil}, nil
|
return &subscription{handler: handler, next: nil}, nil
|
||||||
}
|
}
|
||||||
|
|
16
errors.go
Normal file
16
errors.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package events
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type HandlerError struct {
|
||||||
|
topic string
|
||||||
|
errs []error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h HandlerError) Error() string {
|
||||||
|
return fmt.Sprintf("caught %d errors from topic '%v': %v", len(h.errs), h.topic, h.errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h HandlerError) Unwrap() []error {
|
||||||
|
return h.errs
|
||||||
|
}
|
22
handler.go
22
handler.go
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !tinygo
|
||||||
// +build !tinygo
|
// +build !tinygo
|
||||||
|
|
||||||
package events
|
package events
|
||||||
|
@ -21,7 +22,7 @@ func newReceiptHandler(receiver interface{}) (receiptHandler, error) {
|
||||||
return receiptHandler{receiverFunc: val, funcType: val.Type()}, nil
|
return receiptHandler{receiverFunc: val, funcType: val.Type()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rh *receiptHandler) invoke(values preparedArgs) {
|
func (rh *receiptHandler) invoke(values preparedArgs) error {
|
||||||
args := make([]reflect.Value, rh.funcType.NumIn())
|
args := make([]reflect.Value, rh.funcType.NumIn())
|
||||||
for i := range args {
|
for i := range args {
|
||||||
args[i] = reflect.Zero(rh.funcType.In(i))
|
args[i] = reflect.Zero(rh.funcType.In(i))
|
||||||
|
@ -32,7 +33,22 @@ func (rh *receiptHandler) invoke(values preparedArgs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rh.receiverFunc.Call(args)
|
rets := rh.receiverFunc.Call(args)
|
||||||
|
if len(rets) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRet := rets[len(rets)-1]
|
||||||
|
switch {
|
||||||
|
case lastRet.IsNil():
|
||||||
|
return nil
|
||||||
|
case lastRet.CanInterface():
|
||||||
|
err, ok := lastRet.Interface().(error)
|
||||||
|
if ok {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type preparedArgs []reflect.Value
|
type preparedArgs []reflect.Value
|
||||||
|
@ -43,4 +59,4 @@ func prepareArgs(argIfacess []interface{}) preparedArgs {
|
||||||
values[i] = reflect.ValueOf(a)
|
values[i] = reflect.ValueOf(a)
|
||||||
}
|
}
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue