200 lines
6.2 KiB
Go
200 lines
6.2 KiB
Go
package cqrs
|
|
|
|
import (
|
|
stdErrors "errors"
|
|
|
|
"github.com/ThreeDotsLabs/watermill"
|
|
"github.com/ThreeDotsLabs/watermill/message"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Deprecated: use CommandProcessor and EventProcessor instead.
|
|
type FacadeConfig struct {
|
|
// GenerateCommandsTopic generates topic name based on the command name.
|
|
// Command name is generated by CommandEventMarshaler's Name method.
|
|
//
|
|
// It allows you to use topic per command or one topic for every command.
|
|
GenerateCommandsTopic func(commandName string) string
|
|
|
|
// CommandHandlers return command handlers which should be executed.
|
|
CommandHandlers func(commandBus *CommandBus, eventBus *EventBus) []CommandHandler
|
|
|
|
// CommandsPublisher is Publisher used to publish commands.
|
|
CommandsPublisher message.Publisher
|
|
|
|
// CommandsSubscriberConstructor is constructor for subscribers which will subscribe for messages.
|
|
// It will be called for every command handler.
|
|
// It allows you to create separated customized Subscriber for every command handler.
|
|
CommandsSubscriberConstructor CommandsSubscriberConstructor
|
|
|
|
// GenerateEventsTopic generates topic name based on the event name.
|
|
// Event name is generated by CommandEventMarshaler's Name method.
|
|
//
|
|
// It allows you to use topic per command or one topic for every command.
|
|
GenerateEventsTopic func(eventName string) string
|
|
|
|
// EventHandlers return event handlers which should be executed.
|
|
EventHandlers func(commandBus *CommandBus, eventBus *EventBus) []EventHandler
|
|
|
|
// EventsPublisher is Publisher used to publish commands.
|
|
EventsPublisher message.Publisher
|
|
|
|
// EventsSubscriberConstructor is constructor for subscribers which will subscribe for messages.
|
|
// It will be called for every event handler.
|
|
// It allows you to create separated customized Subscriber for every event handler.
|
|
EventsSubscriberConstructor EventsSubscriberConstructor
|
|
|
|
// Router is a Watermill router, which will be used to handle events and commands.
|
|
// Router handlers will be automatically generated by AddHandlersToRouter of Command and Event handlers.
|
|
Router *message.Router
|
|
|
|
CommandEventMarshaler CommandEventMarshaler
|
|
|
|
Logger watermill.LoggerAdapter
|
|
}
|
|
|
|
func (c FacadeConfig) Validate() error {
|
|
var err error
|
|
|
|
if c.CommandsEnabled() {
|
|
if c.GenerateCommandsTopic == nil {
|
|
err = stdErrors.Join(err, errors.New("GenerateCommandsTopic is nil"))
|
|
}
|
|
if c.CommandsSubscriberConstructor == nil {
|
|
err = stdErrors.Join(err, errors.New("CommandsSubscriberConstructor is nil"))
|
|
}
|
|
if c.CommandsPublisher == nil {
|
|
err = stdErrors.Join(err, errors.New("CommandsPublisher is nil"))
|
|
}
|
|
}
|
|
if c.EventsEnabled() {
|
|
if c.GenerateEventsTopic == nil {
|
|
err = stdErrors.Join(err, errors.New("GenerateEventsTopic is nil"))
|
|
}
|
|
if c.EventsSubscriberConstructor == nil {
|
|
err = stdErrors.Join(err, errors.New("EventsSubscriberConstructor is nil"))
|
|
}
|
|
if c.EventsPublisher == nil {
|
|
err = stdErrors.Join(err, errors.New("EventsPublisher is nil"))
|
|
}
|
|
}
|
|
|
|
if c.Router == nil {
|
|
err = stdErrors.Join(err, errors.New("Router is nil"))
|
|
}
|
|
if c.Logger == nil {
|
|
err = stdErrors.Join(err, errors.New("Logger is nil"))
|
|
}
|
|
if c.CommandEventMarshaler == nil {
|
|
err = stdErrors.Join(err, errors.New("CommandEventMarshaler is nil"))
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func (c FacadeConfig) EventsEnabled() bool {
|
|
return c.GenerateEventsTopic != nil || c.EventsPublisher != nil || c.EventsSubscriberConstructor != nil
|
|
}
|
|
|
|
func (c FacadeConfig) CommandsEnabled() bool {
|
|
return c.GenerateCommandsTopic != nil || c.CommandsPublisher != nil || c.CommandsSubscriberConstructor != nil
|
|
}
|
|
|
|
// Deprecated: use CommandHandler and EventHandler instead.
|
|
//
|
|
// Facade is a facade for creating the Command and Event buses and processors.
|
|
// It was created to avoid boilerplate, when using CQRS in the standard way.
|
|
// You can also create buses and processors manually, drawing inspiration from how it's done in NewFacade.
|
|
type Facade struct {
|
|
commandsTopic func(commandName string) string
|
|
commandBus *CommandBus
|
|
|
|
eventsTopic func(eventName string) string
|
|
eventBus *EventBus
|
|
|
|
commandEventMarshaler CommandEventMarshaler
|
|
}
|
|
|
|
func (f Facade) CommandBus() *CommandBus {
|
|
return f.commandBus
|
|
}
|
|
|
|
func (f Facade) EventBus() *EventBus {
|
|
return f.eventBus
|
|
}
|
|
|
|
func (f Facade) CommandEventMarshaler() CommandEventMarshaler {
|
|
return f.commandEventMarshaler
|
|
}
|
|
|
|
// Deprecated: use CommandHandler and EventHandler instead.
|
|
func NewFacade(config FacadeConfig) (*Facade, error) {
|
|
if err := config.Validate(); err != nil {
|
|
return nil, errors.Wrap(err, "invalid config")
|
|
}
|
|
|
|
c := &Facade{
|
|
commandsTopic: config.GenerateCommandsTopic,
|
|
eventsTopic: config.GenerateEventsTopic,
|
|
commandEventMarshaler: config.CommandEventMarshaler,
|
|
}
|
|
|
|
if config.CommandsEnabled() {
|
|
var err error
|
|
c.commandBus, err = NewCommandBus(
|
|
config.CommandsPublisher,
|
|
config.GenerateCommandsTopic,
|
|
config.CommandEventMarshaler,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "cannot create command bus")
|
|
}
|
|
} else {
|
|
config.Logger.Info("Empty GenerateCommandsTopic, command bus will be not created", nil)
|
|
}
|
|
if config.EventsEnabled() {
|
|
var err error
|
|
c.eventBus, err = NewEventBus(config.EventsPublisher, config.GenerateEventsTopic, config.CommandEventMarshaler)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "cannot create event bus")
|
|
}
|
|
} else {
|
|
config.Logger.Info("Empty GenerateEventsTopic, event bus will be not created", nil)
|
|
}
|
|
|
|
if config.CommandHandlers != nil {
|
|
commandProcessor, err := NewCommandProcessor(
|
|
config.CommandHandlers(c.commandBus, c.eventBus),
|
|
config.GenerateCommandsTopic,
|
|
config.CommandsSubscriberConstructor,
|
|
config.CommandEventMarshaler,
|
|
config.Logger,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "cannot create command processor")
|
|
}
|
|
|
|
if err := commandProcessor.AddHandlersToRouter(config.Router); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if config.EventHandlers != nil {
|
|
eventProcessor, err := NewEventProcessor(
|
|
config.EventHandlers(c.commandBus, c.eventBus),
|
|
config.GenerateEventsTopic,
|
|
config.EventsSubscriberConstructor,
|
|
config.CommandEventMarshaler,
|
|
config.Logger,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "cannot create event processor")
|
|
}
|
|
|
|
if err := eventProcessor.AddHandlersToRouter(config.Router); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return c, nil
|
|
}
|