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 }