-
Notifications
You must be signed in to change notification settings - Fork 0
/
event.go
148 lines (122 loc) · 2.74 KB
/
event.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
146
147
148
package event
import (
"github.com/AltScore/gothic/pkg/ids"
"reflect"
"time"
)
type ID = ids.ID
type AggID = ids.ID
type Aggregate interface {
ID() ids.ID
Type() string
Version() int
}
type IEvent interface {
// ID returns the id of the event.
ID() ID
// Name returns the name of the event.
Name() string
// Time returns the time of the event.
Time() time.Time
// Data returns the event data.
Data() interface{}
// Aggregate returns the id, name and version of the aggregate that the
// event belongs to. aggregate should return zero values if the event is not
// an aggregate event.
Aggregate() (id ids.ID, name string, version int)
}
type Metadata struct {
ID ID
Name string
Time time.Time
AggregateName string
AggregateID AggID
AggregateVersion int
Data interface{}
}
type Event struct {
m *Metadata
}
var EmptyEvent = Event{}
func (e Event) Data() interface{} {
return e.m.Data
}
type Option func(*Metadata)
func New(name string, data any, opts ...Option) Event {
m := Metadata{
ID: ids.New(),
Name: name,
Time: time.Now(),
}
for _, opt := range opts {
opt(&m)
}
return Event{m: &Metadata{
ID: m.ID,
Name: m.Name,
Time: m.Time,
AggregateName: m.AggregateName,
AggregateID: m.AggregateID,
AggregateVersion: m.AggregateVersion,
Data: data,
}}
}
func For[Data any](a Aggregate, name string, data Data, opts ...Option) Event {
return New(name, data, append(opts, WithAggregate(a))...)
}
func (e Event) ID() ID {
return e.m.ID
}
func (e Event) Name() string {
return e.m.Name
}
func (e Event) Time() time.Time {
return e.m.Time
}
func (e Event) Aggregate() (AggID, string, int) {
return e.m.AggregateID, e.m.AggregateName, e.m.AggregateVersion
}
func (e Event) AggregateID() AggID {
return e.m.AggregateID
}
func (e Event) Version() int {
return e.m.AggregateVersion
}
func WithID(id ID) Option {
return func(m *Metadata) {
m.ID = id
}
}
func WithTime(t time.Time) Option {
return func(m *Metadata) {
m.Time = t
}
}
func WithAggregate(a Aggregate) Option {
return func(m *Metadata) {
m.AggregateID = a.ID()
m.AggregateName = a.Type()
m.AggregateVersion = a.Version() + 1
}
}
func WithType(id AggID, typeName string) Option {
return func(m *Metadata) {
m.AggregateID = id
m.AggregateName = typeName
m.AggregateVersion = -1
}
}
func WithTypeAndVersion(id AggID, typeName string, version int) Option {
return func(m *Metadata) {
m.AggregateID = id
m.AggregateName = typeName
m.AggregateVersion = version
}
}
func DataOf[T any](e Event) T {
if data, ok := e.Data().(T); ok {
return data
}
var t T
panic("Event: data is not of type " + reflect.TypeOf(t).String())
}