Part 4: Commands
...
- commands, command handlers, command bus, ...
- show how to add new commands + tests
Since CommandHandlers usually access the AggregateRepository, we first create a structure to facilitate the implementation of subsequent CommandHandlers.
What is a Command?
In the CQRS pattern, a command is a message that represents an intention to change the state of the system. A command is sent to the system and is handled by a CommandHandler. The CommandHandler is responsible for validating the command and emitting events as a result of the command being executed.
Create Command Handler
go
// domain/aqua/command/handler.go
package command
import "github.com/gradientzero/comby/repo"
type cmdDataHandler struct {
AggregateRepository *repo.AggregateRepository
}
func NewCommandDataHandler(
AggregateRepository *repo.AggregateRepository,
) *cmdDataHandler {
cdh := &cmdDataHandler{}
cdh.AggregateRepository = AggregateRepository
return cdh
}
Create New Command
go
// domain/aqua/command/create.go
package command
import (
"context"
"fmt"
"aqua/predict/domain/aqua/aggregate"
"github.com/gradientzero/comby/event"
"github.com/gradientzero/comby/utils"
)
type AddCommand struct {
AquaUuid string `json:"aquaUuid"`
Name string `json:"name"`
}
func (cdh *cmdDataHandler) Add(ctx context.Context, cmdData *AddCommand) ([]event.Event, error) {
var err error
// validate uuid
err = utils.ValidateUuid(cmdData.AquaUuid)
if err != nil {
return nil, fmt.Errorf("%s failed - aquaUuid is invalid", utils.GetTypeName(cmdData))
}
// retrieve existing aggregate from store
_agg, _ := cdh.AggregateRepository.GetAggregate(cmdData.AquaUuid, aggregate.NewAggregate)
if _agg != nil {
return nil, fmt.Errorf("%s failed - aquaUuid already exist", utils.GetTypeName(cmdData))
}
// create new aggregate
_agg = aggregate.NewAggregate()
// cast into a concrete type
agg, ok := _agg.(*aggregate.Aqua)
if !ok {
return nil, fmt.Errorf("%s failed - conversion to concrete aggregate failed", utils.GetTypeName(cmdData))
}
agg.AggregateUuid = cmdData.AquaUuid
// execute logic
err = agg.Add(cmdData.Name)
if err != nil {
return nil, err
}
// return new events
return agg.GetUncommittedEvents(), nil
}