github.com/wfusion/gofusion@v1.1.14/common/infra/watermill/components/cqrs/event_bus.go (about) 1 package cqrs 2 3 import ( 4 "context" 5 6 "github.com/pkg/errors" 7 "go.uber.org/multierr" 8 9 "github.com/wfusion/gofusion/common/infra/watermill" 10 "github.com/wfusion/gofusion/common/infra/watermill/message" 11 ) 12 13 type EventBusConfig struct { 14 // GeneratePublishTopic is used to generate topic name for publishing event. 15 GeneratePublishTopic GenerateEventPublishTopicFn 16 17 // OnPublish is called before sending the event. 18 // The *message.Message can be modified. 19 // 20 // This option is not required. 21 OnPublish OnEventSendFn 22 23 // Marshaler is used to marshal and unmarshal events. 24 // It is required. 25 Marshaler CommandEventMarshaler 26 27 // Logger instance used to log. 28 // If not provided, watermill.NopLogger is used. 29 Logger watermill.LoggerAdapter 30 } 31 32 func (c *EventBusConfig) setDefaults() { 33 if c.Logger == nil { 34 c.Logger = watermill.NopLogger{} 35 } 36 } 37 38 func (c EventBusConfig) Validate() error { 39 var err error 40 41 if c.Marshaler == nil { 42 err = multierr.Append(err, errors.New("missing Marshaler")) 43 } 44 45 if c.GeneratePublishTopic == nil { 46 err = multierr.Append(err, errors.New("missing GenerateHandlerTopic")) 47 } 48 49 return err 50 } 51 52 type GenerateEventPublishTopicFn func(GenerateEventPublishTopicParams) (string, error) 53 54 type GenerateEventPublishTopicParams struct { 55 EventName string 56 Event any 57 } 58 59 type OnEventSendFn func(params OnEventSendParams) error 60 61 type OnEventSendParams struct { 62 EventName string 63 Event any 64 65 // Message is never nil and can be modified. 66 Message *message.Message 67 } 68 69 // EventBus transports events to event handlers. 70 type EventBus struct { 71 publisher message.Publisher 72 config EventBusConfig 73 } 74 75 // NewEventBus creates a new CommandBus. 76 // Deprecated: use NewEventBusWithConfig instead. 77 func NewEventBus( 78 publisher message.Publisher, 79 generateTopic func(eventName string) string, 80 marshaler CommandEventMarshaler, 81 ) (*EventBus, error) { 82 if publisher == nil { 83 return nil, errors.New("missing publisher") 84 } 85 if generateTopic == nil { 86 return nil, errors.New("missing generateTopic") 87 } 88 if marshaler == nil { 89 return nil, errors.New("missing marshaler") 90 } 91 92 return &EventBus{ 93 publisher: publisher, 94 config: EventBusConfig{ 95 GeneratePublishTopic: func(params GenerateEventPublishTopicParams) (string, error) { 96 return generateTopic(params.EventName), nil 97 }, 98 Marshaler: marshaler, 99 }, 100 }, nil 101 } 102 103 // NewEventBusWithConfig creates a new EventBus. 104 func NewEventBusWithConfig(publisher message.Publisher, config EventBusConfig) (*EventBus, error) { 105 if publisher == nil { 106 return nil, errors.New("missing publisher") 107 } 108 109 config.setDefaults() 110 if err := config.Validate(); err != nil { 111 return nil, errors.Wrap(err, "invalid config") 112 } 113 114 return &EventBus{publisher, config}, nil 115 } 116 117 // Publish sends event to the event bus. 118 func (c EventBus) Publish(ctx context.Context, event any) error { 119 msg, err := c.config.Marshaler.Marshal(event) 120 if err != nil { 121 return err 122 } 123 124 eventName := c.config.Marshaler.Name(event) 125 topicName, err := c.config.GeneratePublishTopic(GenerateEventPublishTopicParams{ 126 EventName: eventName, 127 Event: event, 128 }) 129 if err != nil { 130 return errors.Wrap(err, "cannot generate topic") 131 } 132 133 msg.SetContext(ctx) 134 135 if c.config.OnPublish != nil { 136 err := c.config.OnPublish(OnEventSendParams{ 137 EventName: eventName, 138 Event: event, 139 Message: msg, 140 }) 141 if err != nil { 142 return errors.Wrap(err, "cannot execute OnPublish") 143 } 144 } 145 146 return c.publisher.Publish(ctx, topicName, msg) 147 }