Renamed triggers to handlers

This commit is contained in:
Denis Arh
2020-01-18 07:05:35 +01:00
parent 78525b48ea
commit 50fdd5c4c3
9 changed files with 94 additions and 94 deletions
+2 -2
View File
@@ -59,7 +59,7 @@ type (
}
eventRegistry interface {
Register(h eventbus.Handler, ops ...eventbus.TriggerRegOp) uintptr
Register(h eventbus.HandlerFn, ops ...eventbus.HandlerRegOp) uintptr
Unregister(ptrs ...uintptr)
}
@@ -255,7 +255,7 @@ func (svc *service) registerServerScripts(ss ...*ServerScript) {
// registers that script to the list of manual triggers
func (svc *service) registerTriggers(script *ServerScript) []uintptr {
var (
ops []eventbus.TriggerRegOp
ops []eventbus.HandlerRegOp
err error
ptrs = make([]uintptr, 0, len(script.Triggers))
+1 -1
View File
@@ -56,7 +56,7 @@ func pluckManualTriggers(script *ServerScript) map[string]string {
}
// converts trigger's constraint to eventbus' constraint options
func makeTriggerOpts(t *Trigger) (oo []eventbus.TriggerRegOp, err error) {
func makeTriggerOpts(t *Trigger) (oo []eventbus.HandlerRegOp, err error) {
if len(t.Events) == 0 {
return nil, fmt.Errorf("can not generate trigger without at least one events")
}
+1 -1
View File
@@ -66,7 +66,7 @@ func TestTriggerOptsMaking(t *testing.T) {
},
}
oo []eventbus.TriggerRegOp
oo []eventbus.HandlerRegOp
err error
)
+10 -10
View File
@@ -1,6 +1,6 @@
# pkg/eventbus
Package handles event dispatching and trigger registration
Package handles event dispatching and handler registration
## Event
@@ -21,14 +21,14 @@ Deferred events (onTimestamp and onInterval) are executed by scheduler package s
#### Manual events
Manual events (onManual) are a special case.
Events are not (nor should be) triggered directly or through eventbus.
These events are not (nor should be) dispatched directly or through event-bus.
We use it to route requests and pack attributes from the API to the Corredor service
### Event matcher
Matcher is a function on event that helps filtering fired events.
It decides (returns true or false) if fired event is a match for any of a registered triggers
It decides (returns true or false) if fired event is a match for any of a registered handlers
Bus has basic internal filtering for resource & event type.
Other constraints are passed to event's matcher function.
@@ -45,20 +45,20 @@ All constraints must match.
First non-match will break constraint checking procedure.
## Triggers
## Handler
Trigger is combination of (event matching) rules/constraints and event handler.
Handler is a callback function called when a compatible event is fired.
Handler is combination of (event matching) rules/constraints and handler callback function.
Function is called when a event compatible with registered rules & constraints is fired.
Trigger can respond to multiple resource/event combinations.
Handler can respond to multiple resource/event combinations.
### Constraints
Matcher function is called multiple times, once per each trigger constraint.
Matcher function is called multiple times, once per each handler constraint.
If any of the calls result in a non-match, check
Trigger without constraint is considered a match.
Handler without any constraints is considered a match.
### Weight
Weight controls order of trigger execution.
Weight controls order of execution.
+2 -2
View File
@@ -112,11 +112,11 @@ func mustLikeMaker(name string, not bool, vv ...string) (*mustBeLike, error) {
}
func MustBeLike(name string, vv ...string) (ConstraintMatcher, error) {
return &mustBeLike{name: name, values: vv}, nil
return mustLikeMaker(name, false, vv...)
}
func MustNotBeLike(name string, vv ...string) (ConstraintMatcher, error) {
return &mustBeLike{name: name, values: vv, not: true}, nil
return mustLikeMaker(name, true, vv...)
}
func (c mustBeLike) Match(value string) bool {
+18 -18
View File
@@ -24,11 +24,11 @@ type (
wg *sync.WaitGroup
// Read & write locking
// prevent event handling during trigger (un)registration
// prevent event handling during handler (un)registration
l *sync.RWMutex
// list of registered handlers
triggers map[uintptr]*trigger
handlers map[uintptr]*handler
}
)
@@ -50,7 +50,7 @@ func New() *eventbus {
return &eventbus{
wg: &sync.WaitGroup{},
l: &sync.RWMutex{},
triggers: make(map[uintptr]*trigger),
handlers: make(map[uintptr]*handler),
}
}
@@ -61,7 +61,7 @@ func (b *eventbus) WaitFor(ctx context.Context, ev Event) (err error) {
b.l.RLock()
defer b.l.RUnlock()
for _, t := range b.find(ev) {
err = func(ctx context.Context, t *trigger) error {
err = func(ctx context.Context, t *handler) error {
b.wg.Add(1)
defer b.wg.Done()
return t.Handle(ctx, ev)
@@ -82,7 +82,7 @@ func (b *eventbus) Dispatch(ctx context.Context, ev Event) {
defer b.l.RUnlock()
for _, t := range b.find(ev) {
b.wg.Add(1)
go func(ctx context.Context, t *trigger) {
go func(ctx context.Context, t *handler) {
defer b.wg.Done()
_ = t.Handle(ctx, ev)
}(ctx, t)
@@ -96,18 +96,18 @@ func (b *eventbus) wait() {
b.wg.Wait()
}
// Finds all registered triggers compatible with given event
// Finds all registered handlers compatible with given event
//
// It returns sorted triggers
// It returns sorted handlers
//
// There is still room for improvement (performance wise) by indexing
// resources and events of each trigger.
func (b *eventbus) find(ev Event) (tt TriggerSet) {
// resources and events of each handler.
func (b *eventbus) find(ev Event) (tt HandlerSet) {
if ev == nil {
return
}
for _, t := range b.triggers {
for _, t := range b.handlers {
if !t.Match(ev) {
continue
@@ -121,28 +121,28 @@ func (b *eventbus) find(ev Event) (tt TriggerSet) {
return
}
// Register creates a new trigger with given handler, resource, event with other options and constraints
// Register creates a new handler with given handler, resource, event with other options and constraints
//
// It returns a trigger identifier that can be used to remove (unregister) trigger later
func (b *eventbus) Register(h Handler, ops ...TriggerRegOp) uintptr {
// It returns a handler identifier that can be used to remove (unregister) handler later
func (b *eventbus) Register(h HandlerFn, ops ...HandlerRegOp) uintptr {
b.l.Lock()
defer b.l.Unlock()
var (
trigger = NewTrigger(h, ops...)
ptr = uintptr(unsafe.Pointer(trigger))
handlers = NewHandler(h, ops...)
ptr = uintptr(unsafe.Pointer(handlers))
)
b.triggers[ptr] = trigger
b.handlers[ptr] = handlers
return ptr
}
// Unregister removes one or more registered triggers
// Unregister removes one or more registered handlers
func (b *eventbus) Unregister(ptrs ...uintptr) {
b.l.Lock()
defer b.l.Unlock()
for _, ptr := range ptrs {
delete(b.triggers, ptr)
delete(b.handlers, ptr)
}
}
+6 -6
View File
@@ -18,23 +18,23 @@ func TestEventbusRegUnreg(t *testing.T) {
bus = New()
)
a.Empty(bus.triggers)
a.Empty(bus.handlers)
h1 := bus.Register(nil)
a.NotZero(h1)
h2 := bus.Register(nil)
a.NotZero(h2)
h3 := bus.Register(nil)
a.NotZero(h3)
a.Len(bus.triggers, 3)
a.Len(bus.handlers, 3)
bus.Unregister(h1)
a.Len(bus.triggers, 2)
a.Len(bus.handlers, 2)
bus.Unregister(h2)
a.Len(bus.triggers, 1)
a.Len(bus.handlers, 1)
bus.Unregister(h3)
a.Empty(bus.triggers)
a.Empty(bus.handlers)
}
func BenchmarkEventbusTriggerLookup(b *testing.B) {
func BenchmarkEventbusHandlerLookup(b *testing.B) {
var (
bus = New()
ptrs []uintptr
@@ -8,10 +8,10 @@ import (
)
type (
Handler func(ctx context.Context, ev Event) error
HandlerFn func(ctx context.Context, ev Event) error
trigger struct {
handler Handler
handler struct {
handler HandlerFn
resourceTypes map[string]bool
eventTypes map[string]bool
constraints constraintSet
@@ -19,30 +19,30 @@ type (
}
// @todo add sorting interface
TriggerSet []*trigger
HandlerSet []*handler
TriggerRegOp func(t *trigger)
HandlerRegOp func(t *handler)
eventInvokerSettable interface {
SetInvoker(auth.Identifiable)
}
)
// Match matches trigger with resource event
func (t trigger) Match(re Event) bool {
// Match matches handler with resource event
func (t handler) Match(re Event) bool {
if re == nil {
return false
}
if len(re.ResourceType()) == 0 || !t.resourceTypes[re.ResourceType()] {
// Expecting to have valid resource type and match at least one
// defined resource on the trigger
// defined resource on the handler
return false
}
if len(re.EventType()) == 0 || !t.eventTypes[re.EventType()] {
// Expecting to have valid event type and match at least one
// defined event on the trigger
// defined event on the handler
return false
}
@@ -56,7 +56,7 @@ func (t trigger) Match(re Event) bool {
return true
}
func (t trigger) Handle(ctx context.Context, ev Event) error {
func (t handler) Handle(ctx context.Context, ev Event) error {
defer sentry.Recover()
if eis, ok := ev.(eventInvokerSettable); ok {
@@ -66,8 +66,8 @@ func (t trigger) Handle(ctx context.Context, ev Event) error {
return t.handler(ctx, ev)
}
func NewTrigger(h Handler, ops ...TriggerRegOp) *trigger {
var t = &trigger{
func NewHandler(h HandlerFn, ops ...HandlerRegOp) *handler {
var t = &handler{
resourceTypes: make(map[string]bool),
eventTypes: make(map[string]bool),
handler: h,
@@ -80,36 +80,36 @@ func NewTrigger(h Handler, ops ...TriggerRegOp) *trigger {
return t
}
func For(rr ...string) TriggerRegOp {
return func(t *trigger) {
func For(rr ...string) HandlerRegOp {
return func(t *handler) {
for _, r := range rr {
t.resourceTypes[r] = true
}
}
}
func On(ee ...string) TriggerRegOp {
return func(t *trigger) {
func On(ee ...string) HandlerRegOp {
return func(t *handler) {
for _, e := range ee {
t.eventTypes[e] = true
}
}
}
func Constraint(c ConstraintMatcher) TriggerRegOp {
return func(t *trigger) {
func Constraint(c ConstraintMatcher) HandlerRegOp {
return func(t *handler) {
t.constraints = append(t.constraints, c)
}
}
func Weight(weight int) TriggerRegOp {
return func(t *trigger) {
func Weight(weight int) HandlerRegOp {
return func(t *handler) {
t.weight = weight
}
}
// Trigger-set sorting:
// handler sorting:
func (set TriggerSet) Len() int { return len(set) }
func (set TriggerSet) Swap(i, j int) { set[i], set[j] = set[j], set[i] }
func (set TriggerSet) Less(i, j int) bool { return set[i].weight < set[j].weight }
func (set HandlerSet) Len() int { return len(set) }
func (set HandlerSet) Swap(i, j int) { set[i], set[j] = set[j], set[i] }
func (set HandlerSet) Less(i, j int) bool { return set[i].weight < set[j].weight }
@@ -41,10 +41,10 @@ func (e *mockEvent) SetInvoker(identity auth.Identifiable) {
e.identity = identity
}
func TestTrigger_Match(t *testing.T) {
func TestHandler_Match(t *testing.T) {
cases := []struct {
name string
ops []TriggerRegOp
ops []HandlerRegOp
ev Event
match bool
}{
@@ -54,22 +54,22 @@ func TestTrigger_Match(t *testing.T) {
false,
},
{"empty resource",
[]TriggerRegOp{For("foo"), On("bar")},
[]HandlerRegOp{For("foo"), On("bar")},
&mockEvent{rType: "", eType: "bar"},
false,
},
{"empty event",
[]TriggerRegOp{For("foo"), On("bar")},
[]HandlerRegOp{For("foo"), On("bar")},
&mockEvent{rType: "foo", eType: ""},
false,
},
{"simple foo-bar test",
[]TriggerRegOp{For("foo"), On("bar")},
[]HandlerRegOp{For("foo"), On("bar")},
&mockEvent{rType: "foo", eType: "bar"},
true,
},
{"ConstraintMatcher match",
[]TriggerRegOp{For("foo"), On("bar"), Constraint(MustMakeConstraint("baz", "=", "baz"))},
[]HandlerRegOp{For("foo"), On("bar"), Constraint(MustMakeConstraint("baz", "=", "baz"))},
&mockEvent{
rType: "foo",
eType: "bar",
@@ -79,7 +79,7 @@ func TestTrigger_Match(t *testing.T) {
true,
},
{"ConstraintMatcher mismatch",
[]TriggerRegOp{For("foo"), On("bar"), Constraint(MustMakeConstraint("baz", "=", "baz"))},
[]HandlerRegOp{For("foo"), On("bar"), Constraint(MustMakeConstraint("baz", "=", "baz"))},
&mockEvent{
rType: "foo",
eType: "bar",
@@ -92,20 +92,20 @@ func TestTrigger_Match(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
var trigger = NewTrigger(nil, c.ops...)
var handler = NewHandler(nil, c.ops...)
if c.match {
assert.True(t, trigger.Match(c.ev), "Expecting to match")
assert.True(t, handler.Match(c.ev), "Expecting to match")
} else {
assert.False(t, trigger.Match(c.ev), "Expecting to not match")
assert.False(t, handler.Match(c.ev), "Expecting to not match")
}
})
}
}
func TestTrigger_RegOps(t *testing.T) {
makeTestTrigger := func(t *trigger) *trigger {
func TestHandler_RegOps(t *testing.T) {
makeTestHandler := func(t *handler) *handler {
if t.resourceTypes == nil {
t.resourceTypes = make(map[string]bool)
}
@@ -119,45 +119,45 @@ func TestTrigger_RegOps(t *testing.T) {
cases := []struct {
name string
exp *trigger
ops []TriggerRegOp
exp *handler
ops []HandlerRegOp
}{
{
"empty",
makeTestTrigger(&trigger{}),
makeTestHandler(&handler{}),
nil,
},
{
"resource types",
makeTestTrigger(&trigger{resourceTypes: map[string]bool{"foo": true, "bar": true}}),
[]TriggerRegOp{For("foo", "bar")},
makeTestHandler(&handler{resourceTypes: map[string]bool{"foo": true, "bar": true}}),
[]HandlerRegOp{For("foo", "bar")},
},
{
"event types",
makeTestTrigger(&trigger{eventTypes: map[string]bool{"foo": true, "bar": true}}),
[]TriggerRegOp{On("foo", "bar")},
makeTestHandler(&handler{eventTypes: map[string]bool{"foo": true, "bar": true}}),
[]HandlerRegOp{On("foo", "bar")},
},
{
"weight",
makeTestTrigger(&trigger{weight: 42}),
[]TriggerRegOp{Weight(42)},
makeTestHandler(&handler{weight: 42}),
[]HandlerRegOp{Weight(42)},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
assert.Equal(t, c.exp, NewTrigger(nil, c.ops...))
assert.Equal(t, c.exp, NewHandler(nil, c.ops...))
})
}
}
func TestTriggerHandler(t *testing.T) {
func TestHandlerHandler(t *testing.T) {
var (
a = assert.New(t)
ctx = context.Background()
ev = &mockEvent{}
passedthrough bool
trSimple = &trigger{
trSimple = &handler{
handler: func(ctx context.Context, ev Event) error {
passedthrough = true
a.True(auth.IsSuperUser(ev.(*mockEvent).identity))
@@ -175,16 +175,16 @@ func TestTriggerHandler(t *testing.T) {
a.True(passedthrough, "expecting to pass through simple handler")
}
func TestTriggerSorting(t *testing.T) {
func TestHandlerSorting(t *testing.T) {
var (
a = assert.New(t)
tt = TriggerSet{
NewTrigger(nil, Weight(3)),
NewTrigger(nil, Weight(1)),
NewTrigger(nil, Weight(2)),
tt = HandlerSet{
NewHandler(nil, Weight(3)),
NewHandler(nil, Weight(1)),
NewHandler(nil, Weight(2)),
}
w2s = func(tt TriggerSet) (out string) {
w2s = func(tt HandlerSet) (out string) {
for _, t := range tt {
out += fmt.Sprintf("%d,", t.weight)
}