Events
At the framework layer, events are plain Go structs wrapped in a fairway.Event envelope that adds a timestamp.
fairway.Event
OccurredAt— when the event happened (set automatically byNewEvent)Data— the user-defined event struct
Creating Events
// With auto-generated timestamp
event := fairway.NewEvent(ListCreated{ListId: "abc", Name: "Shopping"})
// With an explicit timestamp (for migrations, replays, tests)
event := fairway.NewEventAt(ListCreated{...}, someTime)
User Event Structs
User events are plain Go structs. They can optionally implement two interfaces:
Tags() []string
Scopes the event to a specific entity. Tags are used for filtering in queries.
type ListCreated struct {
ListId string `json:"listId"`
Name string `json:"name"`
}
func (e ListCreated) Tags() []string {
return []string{"list:" + e.ListId}
}
If a struct does not implement Tags(), it is stored without tags (global scope).
TypeString() string
Overrides the event type name used in storage. Defaults to reflect.TypeOf(data).Name().
Use this when you want a stable type name that does not depend on the Go struct name.
Serialization
fairway.Event is serialized to JSON with this envelope structure:
This JSON blob becomes the Data field of the underlying dcb.Event.
The type name (ListCreated by default, or the result of TypeString()) is stored separately as the dcb.Event.Type field and used for indexing and deserialization.
Deserialization
When reading events back from the store, the framework:
- Looks up the type name in its internal registry (populated by
QueryItem.Types(...)) - Unmarshals the JSON envelope to recover
OccurredAt - Unmarshals the inner
datafield into a new instance of the registered Go type - Returns a
fairway.Event{OccurredAt: ..., Data: <concrete struct>}
The handler receives a typed fairway.Event with Data already cast to the correct concrete type. Use a type switch:
func(e fairway.Event) bool {
switch data := e.Data.(type) {
case ListCreated:
// data.ListId, data.Name are available
case ItemAdded:
// data.ItemId is available
}
return true
}
Converting to dcb.Event
If you need to work at the DCB layer directly:
This serializes the fairway.Event to JSON and populates dcb.Event.Type, dcb.Event.Tags, and dcb.Event.Data.