-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathspitfire.go
128 lines (107 loc) · 3.55 KB
/
spitfire.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
package spitfire
import (
"errors"
"fmt"
"log"
)
type commandAndQueryHandler struct {
handlers map[string]func(interface{}) (interface{}, error)
l *log.Logger
}
func (cH *commandAndQueryHandler) Register(command interface{}, handler func(interface{}) (interface{}, error)) {
if cH.handlers == nil {
cH.handlers = make(map[string]func(interface{}) (interface{}, error))
}
var key = fmt.Sprintf("%T", command)
cH.handlers[key] = handler
}
func (cH *commandAndQueryHandler) Handle(command interface{}) (interface{}, error) {
var key = fmt.Sprintf("%T", command)
handler, ok := cH.handlers[key]
if !ok {
errorMessage := fmt.Sprintf("could not find command handler for %T\n", command)
cH.l.Printf(errorMessage)
return nil, errors.New(errorMessage)
}
result, err := handler(command)
return result, err
}
type eventHandler struct {
handlers map[string][]func(interface{}) error
l *log.Logger
}
func (eH *eventHandler) Register(event interface{}, handler func(interface{}) error) {
if eH.handlers == nil {
eH.handlers = make(map[string][]func(interface{}) error)
}
var key = fmt.Sprintf("%T", event)
//get existing handlers
existing, ok := eH.handlers[key]
if ok {
new := append(existing, handler)
eH.handlers[key] = new
} else {
new := make([]func(interface{}) error, 1)
new[0] = handler
eH.handlers[key] = new
}
}
func (eH *eventHandler) Handle(event interface{}) []error {
var key = fmt.Sprintf("%T", event)
handlers, ok := eH.handlers[key]
if !ok {
eH.l.Printf("could not find event handler for %T\n", event)
return nil
}
errors := make([]error, 0)
for _, h := range handlers {
e := h(event)
if e != nil {
errors[len(errors)] = e
}
}
return errors
}
// Handler is used to register handlers and receives commands, events and queries then routes them to appropriate handlers
type Handler struct {
eventHandler *eventHandler
commandHandler *commandAndQueryHandler
}
// EventHandler is a function that can handle a given event
type EventHandler = func(interface{}) error
// QueryHandler is a function that can handle a given query
type QueryHandler = func(interface{}) (interface{}, error)
// CommandHandler is a function that can handle a given command
type CommandHandler = func(interface{}) (interface{}, error)
// New sets up the handler and its dependencies
func New(l *log.Logger) *Handler {
eH := &eventHandler{l: l}
cH := &commandAndQueryHandler{l: l}
h := &Handler{eventHandler: eH, commandHandler: cH}
return h
}
// RegisterEventHandler takes in an event and a function to handle that command
func (h *Handler) RegisterEventHandler(event interface{}, handler EventHandler) {
h.eventHandler.Register(event, handler)
}
// RegisterCommandHandler takes in a command and a function to handle that command
func (h *Handler) RegisterCommandHandler(command interface{}, handler CommandHandler) {
h.commandHandler.Register(command, handler)
}
// RegisterQueryHandler takes in a query and a function to handle that command
func (h *Handler) RegisterQueryHandler(command interface{}, handler QueryHandler) {
h.commandHandler.Register(command, handler)
}
// Handle receives a message and calls handlers for that message type and any subsequent events it generates
// It will return the command or query handler result to the caller and an array of any detected errors
func (h *Handler) Handle(message interface{}) (interface{}, []error) {
result, err := h.commandHandler.Handle(message)
if err != nil {
return nil, []error{err}
}
errs := h.eventHandler.Handle(result)
if len(errs) > 0 {
return nil, errs
}
return result, nil
}