-
Notifications
You must be signed in to change notification settings - Fork 0
/
model.event.go
133 lines (109 loc) · 3.76 KB
/
model.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
package eventsource
import (
"context"
"encoding/json"
"fmt"
"sort"
"strings"
"time"
)
func Sort(ee []Event) {
sort.Slice(ee, func(i, j int) bool {
return ee[i].AggregateVersion() < ee[j].AggregateVersion()
})
}
type Event interface {
fmt.Stringer
ApplyTo(ctx context.Context, aggregate Aggregate) // ApplyTo applies the event to the aggregate
ID() EventID // ID returns the id of the event.
Type() EventType // Type returns the type of the event.
OccurredAt() time.Time // OccurredAt of when the event was created.
AggregateID() AggregateID // AggregateID is the id of the aggregate that the event belongs to.
AggregateType() AggregateType // AggregateType is the type of the aggregate that the event can be applied to.
AggregateVersion() AggregateVersion // AggregateVersion is the version of the aggregate after the event has been applied.
SetVersion(AggregateVersion) // SetVersion sets the aggregate version of the event
Metadata() Metadata // Metadata is app-specific metadata such as request AggregateID, originating user etc.
}
func NewMetadata() Metadata {
return Metadata{}
}
type Metadata map[string]interface{}
func (m Metadata) Add(key string, value interface{}) Metadata {
m[key] = value
return m
}
type EventType string
func (t EventType) String() string {
return string(t)
}
func (t EventType) IsZero() bool {
return len(strings.TrimSpace(t.String())) == 0
}
func NewBaseEvent(from Aggregate, metadata Metadata) *BaseEvent {
return initBaseEvent(NewEventID(), time.Now(), from.ID(), from.Type(), from.Version(), metadata)
}
func initBaseEvent(id EventID, occurredAt time.Time, aggregateID AggregateID, aggregateType AggregateType, version AggregateVersion, metadata Metadata) *BaseEvent {
if metadata == nil {
metadata = make(Metadata, 0)
}
return &BaseEvent{
id: id,
occurredAt: occurredAt,
aggregateID: aggregateID,
aggregateType: aggregateType,
aggregateVersion: version,
metadata: metadata,
}
}
type BaseEvent struct {
id EventID
occurredAt time.Time
aggregateID AggregateID
aggregateType AggregateType
aggregateVersion AggregateVersion
metadata map[string]interface{}
}
func (e *BaseEvent) ID() EventID {
return e.id
}
func (e *BaseEvent) OccurredAt() time.Time {
return e.occurredAt
}
func (e *BaseEvent) AggregateID() AggregateID {
return e.aggregateID
}
func (e *BaseEvent) AggregateType() AggregateType {
return e.aggregateType
}
func (e *BaseEvent) AggregateVersion() AggregateVersion {
return e.aggregateVersion
}
func (e *BaseEvent) Metadata() Metadata {
return e.metadata
}
func (e *BaseEvent) String() string {
return fmt.Sprintf("event '%s' occurred on aggregate '%s' (v%d => v%d) with id '%s'", e.ID(), e.AggregateType(), e.aggregateVersion-1, e.aggregateVersion, e.AggregateID())
}
func (e *BaseEvent) SetVersion(version AggregateVersion) {
e.aggregateVersion = version
}
type EventReadModel struct {
ID EventID `json:"id"`
Type EventType `json:"type"`
OccurredAt time.Time `json:"occurred_at"`
AggregateID AggregateID `json:"aggregate_id"`
AggregateType AggregateType `json:"aggregate_type"`
AggregateVersion AggregateVersion `json:"aggregate_version"`
Metadata map[string]interface{} `json:"metadata"`
Data json.RawMessage `json:"data"`
}
func (r *EventReadModel) InitBaseEvent() *BaseEvent {
return initBaseEvent(
r.ID,
r.OccurredAt,
r.AggregateID,
r.AggregateType,
r.AggregateVersion,
r.Metadata,
)
}