forked from andrewwebber/cqrs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
type-registry.go
112 lines (86 loc) · 2.9 KB
/
type-registry.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
package cqrs
import (
"reflect"
"strings"
)
var methodHandlerPrefix = "Handle"
// HandlersCache is a map of types to functions that will be used to route event sourcing events
type HandlersCache map[reflect.Type]func(source interface{}, event interface{})
// EventTypeCache is a map of strings to reflect.Type structures
type EventTypeCache map[string]reflect.Type
// TypeRegistry providers a helper registry for mapping event types and handlers after performance json serializaton
type TypeRegistry interface {
GetHandlers(interface{}) HandlersCache
GetEventType(string) (reflect.Type, bool)
RegisterAggregate(aggregate interface{}, events ...interface{})
RegisterEvents(events ...interface{})
RegisterType(interface{})
}
type defaultTypeRegistry struct {
HandlersDirectory map[reflect.Type]HandlersCache
EventTypes EventTypeCache
}
var cachedRegistry *defaultTypeRegistry
// NewTypeRegistry constructs a new TypeRegistry
func NewTypeRegistry() TypeRegistry {
return newTypeRegistry()
}
func newTypeRegistry() *defaultTypeRegistry {
if cachedRegistry == nil {
handlersDirectory := make(map[reflect.Type]HandlersCache, 0)
eventTypes := make(EventTypeCache, 0)
cachedRegistry = &defaultTypeRegistry{handlersDirectory, eventTypes}
}
return cachedRegistry
}
func (r *defaultTypeRegistry) GetHandlers(source interface{}) HandlersCache {
sourceType := reflect.TypeOf(source)
var handlers HandlersCache
if value, ok := r.HandlersDirectory[sourceType]; ok {
handlers = value
} else {
handlers = createHandlersCache(source)
r.HandlersDirectory[sourceType] = handlers
}
return handlers
}
func (r *defaultTypeRegistry) GetEventType(eventType string) (reflect.Type, bool) {
if eventTypeValue, ok := r.EventTypes[eventType]; ok {
return eventTypeValue, ok
}
return nil, false
}
func (r *defaultTypeRegistry) RegisterType(source interface{}) {
rawType := reflect.TypeOf(source)
r.EventTypes[rawType.String()] = rawType
}
func (r *defaultTypeRegistry) RegisterAggregate(aggregate interface{}, events ...interface{}) {
r.RegisterType(aggregate)
r.RegisterEvents(events)
}
func (r *defaultTypeRegistry) RegisterEvents(events ...interface{}) {
for _, event := range events {
r.RegisterType(event)
}
}
func createHandlersCache(source interface{}) HandlersCache {
sourceType := reflect.TypeOf(source)
handlers := make(HandlersCache)
methodCount := sourceType.NumMethod()
for i := 0; i < methodCount; i++ {
method := sourceType.Method(i)
if strings.HasPrefix(method.Name, methodHandlerPrefix) {
// func (source *MySource) HandleMyEvent(e MyEvent).
if method.Type.NumIn() == 2 {
eventType := method.Type.In(1)
handler := func(source interface{}, event interface{}) {
sourceValue := reflect.ValueOf(source)
eventValue := reflect.ValueOf(event)
method.Func.Call([]reflect.Value{sourceValue, eventValue})
}
handlers[eventType] = handler
}
}
}
return handlers
}