github.com/wfusion/gofusion@v1.1.14/common/infra/watermill/components/cqrs/cqrs.go (about)

     1  package cqrs
     2  
     3  import (
     4  	"github.com/pkg/errors"
     5  	"go.uber.org/multierr"
     6  
     7  	"github.com/wfusion/gofusion/common/infra/watermill"
     8  	"github.com/wfusion/gofusion/common/infra/watermill/message"
     9  )
    10  
    11  // Deprecated: use CommandProcessor and EventProcessor instead.
    12  type FacadeConfig struct {
    13  	// GenerateCommandsTopic generates topic name based on the command name.
    14  	// Command name is generated by CommandEventMarshaler's Name method.
    15  	//
    16  	// It allows you to use topic per command or one topic for every command.
    17  	GenerateCommandsTopic func(commandName string) string
    18  
    19  	// CommandHandlers return command handlers which should be executed.
    20  	CommandHandlers func(commandBus *CommandBus, eventBus *EventBus) []CommandHandler
    21  
    22  	// CommandsPublisher is Publisher used to publish commands.
    23  	CommandsPublisher message.Publisher
    24  
    25  	// CommandsSubscriberConstructor is constructor for subscribers which will subscribe for messages.
    26  	// It will be called for every command handler.
    27  	// It allows you to create separated customized Subscriber for every command handler.
    28  	CommandsSubscriberConstructor CommandsSubscriberConstructor
    29  
    30  	// GenerateEventsTopic generates topic name based on the event name.
    31  	// Event name is generated by CommandEventMarshaler's Name method.
    32  	//
    33  	// It allows you to use topic per command or one topic for every command.
    34  	GenerateEventsTopic func(eventName string) string
    35  
    36  	// EventHandlers return event handlers which should be executed.
    37  	EventHandlers func(commandBus *CommandBus, eventBus *EventBus) []EventHandler
    38  
    39  	// EventsPublisher is Publisher used to publish commands.
    40  	EventsPublisher message.Publisher
    41  
    42  	// EventsSubscriberConstructor is constructor for subscribers which will subscribe for messages.
    43  	// It will be called for every event handler.
    44  	// It allows you to create separated customized Subscriber for every event handler.
    45  	EventsSubscriberConstructor EventsSubscriberConstructor
    46  
    47  	// Router is a Watermill router, which will be used to handle events and commands.
    48  	// Router handlers will be automatically generated by AddHandlersToRouter of Command and Event handlers.
    49  	Router *message.Router
    50  
    51  	CommandEventMarshaler CommandEventMarshaler
    52  
    53  	Logger watermill.LoggerAdapter
    54  }
    55  
    56  func (c FacadeConfig) Validate() error {
    57  	var err error
    58  
    59  	if c.CommandsEnabled() {
    60  		if c.GenerateCommandsTopic == nil {
    61  			err = multierr.Append(err, errors.New("GenerateCommandsTopic is nil"))
    62  		}
    63  		if c.CommandsSubscriberConstructor == nil {
    64  			err = multierr.Append(err, errors.New("CommandsSubscriberConstructor is nil"))
    65  		}
    66  		if c.CommandsPublisher == nil {
    67  			err = multierr.Append(err, errors.New("CommandsPublisher is nil"))
    68  		}
    69  	}
    70  	if c.EventsEnabled() {
    71  		if c.GenerateEventsTopic == nil {
    72  			err = multierr.Append(err, errors.New("GenerateEventsTopic is nil"))
    73  		}
    74  		if c.EventsSubscriberConstructor == nil {
    75  			err = multierr.Append(err, errors.New("EventsSubscriberConstructor is nil"))
    76  		}
    77  		if c.EventsPublisher == nil {
    78  			err = multierr.Append(err, errors.New("EventsPublisher is nil"))
    79  		}
    80  	}
    81  
    82  	if c.Router == nil {
    83  		err = multierr.Append(err, errors.New("Router is nil"))
    84  	}
    85  	if c.Logger == nil {
    86  		err = multierr.Append(err, errors.New("Logger is nil"))
    87  	}
    88  	if c.CommandEventMarshaler == nil {
    89  		err = multierr.Append(err, errors.New("CommandEventMarshaler is nil"))
    90  	}
    91  
    92  	return err
    93  }
    94  
    95  func (c FacadeConfig) EventsEnabled() bool {
    96  	return c.GenerateEventsTopic != nil || c.EventsPublisher != nil || c.EventsSubscriberConstructor != nil
    97  }
    98  
    99  func (c FacadeConfig) CommandsEnabled() bool {
   100  	return c.GenerateCommandsTopic != nil || c.CommandsPublisher != nil || c.CommandsSubscriberConstructor != nil
   101  }
   102  
   103  // Deprecated: use CommandHandler and EventHandler instead.
   104  //
   105  // Facade is a facade for creating the Command and Event buses and processors.
   106  // It was created to avoid boilerplate, when using CQRS in the standard way.
   107  // You can also create buses and processors manually, drawing inspiration from how it's done in NewFacade.
   108  type Facade struct {
   109  	commandsTopic func(commandName string) string
   110  	commandBus    *CommandBus
   111  
   112  	eventsTopic func(eventName string) string
   113  	eventBus    *EventBus
   114  
   115  	commandEventMarshaler CommandEventMarshaler
   116  }
   117  
   118  func (f Facade) CommandBus() *CommandBus {
   119  	return f.commandBus
   120  }
   121  
   122  func (f Facade) EventBus() *EventBus {
   123  	return f.eventBus
   124  }
   125  
   126  func (f Facade) CommandEventMarshaler() CommandEventMarshaler {
   127  	return f.commandEventMarshaler
   128  }
   129  
   130  // Deprecated: use CommandHandler and EventHandler instead.
   131  func NewFacade(config FacadeConfig) (*Facade, error) {
   132  	if err := config.Validate(); err != nil {
   133  		return nil, errors.Wrap(err, "invalid config")
   134  	}
   135  
   136  	c := &Facade{
   137  		commandsTopic:         config.GenerateCommandsTopic,
   138  		eventsTopic:           config.GenerateEventsTopic,
   139  		commandEventMarshaler: config.CommandEventMarshaler,
   140  	}
   141  
   142  	if config.CommandsEnabled() {
   143  		var err error
   144  		c.commandBus, err = NewCommandBus(
   145  			config.CommandsPublisher,
   146  			config.GenerateCommandsTopic,
   147  			config.CommandEventMarshaler,
   148  		)
   149  		if err != nil {
   150  			return nil, errors.Wrap(err, "cannot create command bus")
   151  		}
   152  	} else {
   153  		config.Logger.Info("Empty GenerateCommandsTopic, command bus will be not created", nil)
   154  	}
   155  	if config.EventsEnabled() {
   156  		var err error
   157  		c.eventBus, err = NewEventBus(config.EventsPublisher, config.GenerateEventsTopic, config.CommandEventMarshaler)
   158  		if err != nil {
   159  			return nil, errors.Wrap(err, "cannot create event bus")
   160  		}
   161  	} else {
   162  		config.Logger.Info("Empty GenerateEventsTopic, event bus will be not created", nil)
   163  	}
   164  
   165  	if config.CommandHandlers != nil {
   166  		commandProcessor, err := NewCommandProcessor(
   167  			config.CommandHandlers(c.commandBus, c.eventBus),
   168  			config.GenerateCommandsTopic,
   169  			config.CommandsSubscriberConstructor,
   170  			config.CommandEventMarshaler,
   171  			config.Logger,
   172  		)
   173  		if err != nil {
   174  			return nil, errors.Wrap(err, "cannot create command processor")
   175  		}
   176  
   177  		if err := commandProcessor.AddHandlersToRouter(config.Router); err != nil {
   178  			return nil, err
   179  		}
   180  	}
   181  	if config.EventHandlers != nil {
   182  		eventProcessor, err := NewEventProcessor(
   183  			config.EventHandlers(c.commandBus, c.eventBus),
   184  			config.GenerateEventsTopic,
   185  			config.EventsSubscriberConstructor,
   186  			config.CommandEventMarshaler,
   187  			config.Logger,
   188  		)
   189  		if err != nil {
   190  			return nil, errors.Wrap(err, "cannot create event processor")
   191  		}
   192  
   193  		if err := eventProcessor.AddHandlersToRouter(config.Router); err != nil {
   194  			return nil, err
   195  		}
   196  	}
   197  
   198  	return c, nil
   199  }