package main import ( "context" "encoding/json" "errors" "time" "github.com/EventStore/EventStore-Client-Go/v4/esdb" "github.com/google/uuid" aggregate_model "entrlcom.dev/event-sourcing/domain/model/aggregate" aggregate_id_model "entrlcom.dev/event-sourcing/domain/model/aggregate/id" event_model "entrlcom.dev/event-sourcing/domain/model/event" eventstore_repository "entrlcom.dev/event-sourcing/infra/repository/aggregate/eventstore" ) func main() { ctx := context.Background() // EventStore configuration. eventStoreDBConfiguration, err := esdb.ParseConnectionString("esdb://localhost:2113/?tls=false") if err != nil { return } // EventStore client. eventStoreDBClient, err := esdb.NewClient(eventStoreDBConfiguration) if err != nil { return } // Repository. repository := eventstore_repository.NewEventStoreAggregateRepository(*eventStoreDBClient) // New account (aggregate). account, err := NewAccount(NewAccountID()) if err != nil { return } // Load account (aggregate). if err = repository.Load(ctx, account._aggregate); err != nil { if !errors.Is(err, aggregate_model.ErrAggregateNotFound) { return } } if err = account.ChangeName("A"); err != nil { return } if err = account.ChangeName("B"); err != nil { return } // Save account (aggregate). if err = repository.Save(ctx, account._aggregate); err != nil { return } if err = account.ChangeName("C"); err != nil { return } if err = account.ChangeName("D"); err != nil { return } // Save account (aggregate). if err = repository.Save(ctx, account._aggregate); err != nil { return } } var ErrInvalidAccount = errors.New("invalid account") const AggregateType = "Account" type Account struct { _aggregate *aggregate_model.BaseAggregate id AccountID name string } func (x *Account) ChangeName(name string) error { event := NewAccountNameChangedEvent(x.id.String(), name) data, _ := json.Marshal(event) e, err := event_model.NewBaseEvent( AccountNameChangedEventType, event_model.WithAggregate( x._aggregate.GetID(), x._aggregate.GetType(), x._aggregate.GetVersion(), ), event_model.WithData(data), ) if err != nil { return err } if err = x._aggregate.ApplyEvent(&e); err != nil { return err } return nil } func NewAccount(id AccountID) (*Account, error) { x := Account{ _aggregate: nil, id: id, name: "", } aggregateID, err := aggregate_id_model.NewAggregateIDFromString(id.String()) if err != nil { return nil, errors.Join(err, ErrInvalidAccount) } aggregate, err := aggregate_model.NewBaseAggregate( aggregateID, AggregateType, aggregate_model.WithWhen(func(event event_model.Event) error { switch event.GetType() { case AccountNameChangedEventType: var data AccountNameChangedEvent if err = json.Unmarshal(event.GetData(), &data); err != nil { return err } x.name = data.Name return nil default: return nil } }), ) if err != nil { return nil, errors.Join(err, ErrInvalidAccount) } x._aggregate = &aggregate return &x, nil } var ErrInvalidAccountID = errors.New("invalid account id") type AccountID string func (x AccountID) IsEqualTo(accountID AccountID) bool { return x == accountID } func (x AccountID) String() string { return string(x) } func (x AccountID) Validate() error { v, err := uuid.Parse(string(x)) if err != nil || v.Variant() != uuid.RFC4122 || v.Version() != 7 { return ErrInvalidAccountID } return nil } func NewAccountID() AccountID { return AccountID(uuid.Must(uuid.NewV7()).String()) } const AccountNameChangedEventType = "AccountNameChanged" type AccountNameChangedEvent struct { AccountID string `json:"account_id,omitempty"` Name string `json:"name,omitempty"` } func NewAccountNameChangedEvent(accountID, name string) AccountNameChangedEvent { return AccountNameChangedEvent{ AccountID: accountID, Name: name, } }
- Notifications
You must be signed in to change notification settings - Fork 0
Event Sourcing in Go/Golang
License
flida-dev/go-event-sourcing
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
About
Event Sourcing in Go/Golang
Topics
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published