package cqrs import ( "errors" "fmt" "github.com/ThreeDotsLabs/watermill/message" ) // CommandEventMarshaler marshals Commands and Events to Watermill's messages and vice versa. // Payload of the command needs to be marshaled to []bytes. type CommandEventMarshaler interface { // Marshal marshals Command or Event to Watermill's message. Marshal(v interface{}) (*message.Message, error) // Unmarshal unmarshals watermill's message to v Command or Event. Unmarshal(msg *message.Message, v interface{}) (err error) // Name returns the name of Command or Event. // Name is used to determine, that received command or event is event which we want to handle. Name(v interface{}) string // NameFromMessage returns the name of Command or Event from Watermill's message (generated by Marshal). // // When we have Command or Event marshaled to Watermill's message, // we should use NameFromMessage instead of Name to avoid unnecessary unmarshaling. NameFromMessage(msg *message.Message) string } // CommandEventMarshalerDecorator decorates CommandEventMarshaler with additional functionality. // It can be used to add additional metadata to the message. type CommandEventMarshalerDecorator struct { CommandEventMarshaler // DecorateFunc is called after marshaling the message. DecorateFunc func(v any, msg *message.Message) error } // Marshal marshals Command or Event to Watermill's message and decorates it. func (c CommandEventMarshalerDecorator) Marshal(v any) (*message.Message, error) { msg, err := c.CommandEventMarshaler.Marshal(v) if err != nil { return nil, err } if c.DecorateFunc == nil { return nil, errors.New("DecorateFunc is nil") } if err := c.DecorateFunc(v, msg); err != nil { return nil, fmt.Errorf("cannot decorate message: %w", err) } return msg, nil }