-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
145 lines (119 loc) · 2.93 KB
/
router.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package eventrouter
import (
"regexp"
)
type EventRouter struct {
hooks []IHook
handlers map[string][]IHandler
matchers map[*regexp.Regexp]string
// lock sync.RWMutex
}
func NewEventRouter() *EventRouter {
return &EventRouter{
hooks: []IHook{},
handlers: make(map[string][]IHandler),
matchers: make(map[*regexp.Regexp]string),
// lock: sync.RWMutex{},
}
}
func (eb *EventRouter) Handlers() map[string][]IHandler {
return eb.handlers
}
func (eb *EventRouter) Bind(handler IHandler) error {
route := handler.Route()
if _, ok := eb.handlers[route]; !ok {
eb.handlers[route] = []IHandler{}
}
// check if the handler is already registered
for _, h := range eb.handlers[route] {
if h == handler {
return nil
}
}
matcher, err := regexp.Compile(route)
if err != nil {
return err
}
eb.matchers[matcher] = route
eb.handlers[route] = append(eb.handlers[route], handler)
return nil
}
func (eb *EventRouter) BindFunc(route string, handlerFunc HandlerFunc, hooks ...IHook) error {
return eb.Bind(NewHandler(route, handlerFunc, hooks...))
}
func (eb *EventRouter) Unbind(handler IHandler) *EventRouter {
route := handler.Route()
if _, ok := eb.handlers[route]; !ok {
return eb
}
for i, h := range eb.handlers[route] {
if h == handler {
eb.handlers[route] = append(eb.handlers[route][:i], eb.handlers[route][i+1:]...)
// if there are no more handlers for the route, remove the route
if len(eb.handlers[route]) == 0 {
delete(eb.handlers, route)
for matcher, r := range eb.matchers {
if r == route {
delete(eb.matchers, matcher)
}
}
}
return eb
}
}
return eb
}
func (eb *EventRouter) BindHook(hooks ...IHook) *EventRouter {
eb.hooks = append(eb.hooks, hooks...)
return eb
}
func (eb *EventRouter) UnbindHook(hook IHook) *EventRouter {
for i, h := range eb.hooks {
if h == hook {
eb.hooks = append(eb.hooks[:i], eb.hooks[i+1:]...)
return eb
}
}
return eb
}
func (eb *EventRouter) BindHookFunc(hookFunc ...HookFunc) *EventRouter {
for _, fn := range hookFunc {
eb.BindHook(NewHook(fn))
}
return eb
}
func (eb *EventRouter) run(e IEvent, h IHandler) error {
handlerFn := func(e IEvent) error {
return h.Handle(e)
}
if h.Hooks() != nil {
// iterate over the hooks in reverse order
for i := len(h.Hooks()) - 1; i >= 0; i-- {
handlerFn = h.Hooks()[i].Handle(handlerFn)
}
}
// global hooks
if eb.hooks != nil {
// iterate over the hooks in reverse order
for i := len(eb.hooks) - 1; i >= 0; i-- {
handlerFn = eb.hooks[i].Handle(handlerFn)
}
}
return handlerFn(e)
}
func (eb *EventRouter) Handle(e IEvent) error {
// iterate over the handlers and check if the regex matches
toRun := []IHandler{}
for matcher, route := range eb.matchers {
if matcher.MatchString(e.Name()) {
toRun = append(toRun, eb.handlers[route]...)
}
}
for _, handler := range toRun {
err := eb.run(e, handler)
if err != nil {
return err
}
}
return nil
}