Event Sourcing
How to declare an event store with cfgevs.Enable and a schema per event type. You can inspect and create the stored events in the admin center.
package main
import (
"time"
"github.com/worldiety/option"
"go.wdy.de/nago/application"
"go.wdy.de/nago/application/evs"
cfgevs "go.wdy.de/nago/application/evs/cfg"
cfginspector "go.wdy.de/nago/application/inspector/cfg"
"go.wdy.de/nago/application/user"
"go.wdy.de/nago/auth"
"go.wdy.de/nago/presentation/core"
"go.wdy.de/nago/presentation/ui"
"go.wdy.de/nago/web/vuejs"
)
type Location string
type ShopEvent interface {
Event()
Location() Location
}
type OrderPlaced struct {
ArticleID string
Comment string
OrderID string
Loc Location
}
func (e OrderPlaced) Location() Location {
return e.Loc
}
func (OrderPlaced) Event() {}
type OrderPayed struct {
OrderID string
Loc Location
}
func (e OrderPayed) Location() Location {
return e.Loc
}
func (OrderPayed) Event() {}
type OrderCancelled struct {
OrderID string
Loc Location
}
func (e OrderCancelled) Location() Location {
return e.Loc
}
func (OrderCancelled) Event() {}
func main() {
application.Configure(func(cfg *application.Configurator) {
cfg.SetApplicationID("de.worldiety.tutorial_85")
cfg.Serve(vuejs.Dist())
option.MustZero(cfg.StandardSystems())
option.Must(option.Must(cfg.UserManagement()).UseCases.EnableBootstrapAdmin(time.Now().Add(time.Hour), "%6UbRsCuM8N$auy"))
cfg.SetDecorator(cfg.NewScaffold().Decorator())
option.Must(cfginspector.Enable(cfg))
modShop := option.Must(cfgevs.Enable[ShopEvent](cfg, "test.nago.app", "Shop Events", cfgevs.Options[ShopEvent]{}.WithOptions(
cfgevs.Schema[OrderPlaced, ShopEvent]("OrderPlaced"),
cfgevs.Schema[OrderPayed, ShopEvent]("OrderPayed"),
cfgevs.Schema[OrderCancelled, ShopEvent]("OrderCancelled"),
)))
// take a look for the things you can build your use cases on
_ = modShop
cfg.RootViewWithDecoration(".", func(wnd core.Window) core.View {
return ui.Text("See the admin center")
})
}).Run()
}
// Architecture style note:
// To align your code better with Event Storming keep your use case function declaration but summarize
// your arguments into a single struct called <UseCaseName>Cmd. The Result of that function is
// the Event which has been stored. See the example below
type PayOrderCmd struct {
OrderID string
}
type PayOrder func(subject auth.Subject, cmd PayOrderCmd) (OrderPayed, error)
func NewPayOrder(storeEvent evs.Store[ShopEvent]) PayOrder {
return func(subject auth.Subject, cmd PayOrderCmd) (OrderPayed, error) {
// permission checks and validation stuff and other bussiness logic
// if err:=subject(....
// ...
evt := OrderPayed{OrderID: cmd.OrderID}
if _, err := storeEvent(user.SU(), evt); err != nil {
return evt, err
}
return evt, nil
}
}
View on GitHub ↗
· run it with go run go.wdy.de/nago/example/cmd/tutorial-85-eventsourcing@latest