github.com/vmware/transport-go@v1.3.4/bus/eventbus.go (about) 1 // Copyright 2019-2020 VMware, Inc. 2 // SPDX-License-Identifier: BSD-2-Clause 3 4 package bus 5 6 import ( 7 "fmt" 8 "github.com/google/uuid" 9 "github.com/vmware/transport-go/bridge" 10 "github.com/vmware/transport-go/model" 11 "github.com/vmware/transport-go/stompserver" 12 "sync" 13 "sync/atomic" 14 ) 15 16 const TRANSPORT_INTERNAL_CHANNEL_PREFIX = "_transportInternal/" 17 18 // EventBus provides access to ChannelManager, simple message sending and simple API calls for handling 19 // messaging and error handling over channels on the bus. 20 type EventBus interface { 21 GetId() *uuid.UUID 22 GetChannelManager() ChannelManager 23 SendRequestMessage(channelName string, payload interface{}, destinationId *uuid.UUID) error 24 SendResponseMessage(channelName string, payload interface{}, destinationId *uuid.UUID) error 25 SendBroadcastMessage(channelName string, payload interface{}) error 26 SendErrorMessage(channelName string, err error, destinationId *uuid.UUID) error 27 ListenStream(channelName string) (MessageHandler, error) 28 ListenStreamForDestination(channelName string, destinationId *uuid.UUID) (MessageHandler, error) 29 ListenFirehose(channelName string) (MessageHandler, error) 30 ListenRequestStream(channelName string) (MessageHandler, error) 31 ListenRequestStreamForDestination(channelName string, destinationId *uuid.UUID) (MessageHandler, error) 32 ListenRequestOnce(channelName string) (MessageHandler, error) 33 ListenRequestOnceForDestination(channelName string, destinationId *uuid.UUID) (MessageHandler, error) 34 ListenOnce(channelName string) (MessageHandler, error) 35 ListenOnceForDestination(channelName string, destId *uuid.UUID) (MessageHandler, error) 36 RequestOnce(channelName string, payload interface{}) (MessageHandler, error) 37 RequestOnceForDestination(channelName string, payload interface{}, destId *uuid.UUID) (MessageHandler, error) 38 RequestStream(channelName string, payload interface{}) (MessageHandler, error) 39 RequestStreamForDestination(channelName string, payload interface{}, destId *uuid.UUID) (MessageHandler, error) 40 ConnectBroker(config *bridge.BrokerConnectorConfig) (conn bridge.Connection, err error) 41 StartFabricEndpoint(connectionListener stompserver.RawConnectionListener, config EndpointConfig) error 42 StopFabricEndpoint() error 43 GetStoreManager() StoreManager 44 CreateSyncTransaction() BusTransaction 45 CreateAsyncTransaction() BusTransaction 46 AddMonitorEventListener(listener MonitorEventHandler, eventTypes ...MonitorEventType) MonitorEventListenerId 47 RemoveMonitorEventListener(listenerId MonitorEventListenerId) 48 SendMonitorEvent(evtType MonitorEventType, entityName string, data interface{}) 49 } 50 51 var enableLogging bool = false 52 53 func EnableLogging(enable bool) { 54 enableLogging = enable 55 } 56 57 var once sync.Once 58 var busInstance EventBus 59 60 // ResetBus destroys existing bus instance and creates a new one 61 func ResetBus() EventBus { 62 once = sync.Once{} 63 return GetBus() 64 } 65 66 // Get a reference to the EventBus. 67 func GetBus() EventBus { 68 once.Do(func() { 69 busInstance = NewEventBusInstance() 70 }) 71 return busInstance 72 } 73 74 func NewEventBusInstance() EventBus { 75 bf := new(transportEventBus) 76 bf.init() 77 return bf 78 } 79 80 type transportEventBus struct { 81 ChannelManager ChannelManager 82 storeManager StoreManager 83 Id uuid.UUID 84 brokerConnections map[*uuid.UUID]bridge.Connection 85 bc bridge.BrokerConnector 86 fabEndpoint FabricEndpoint 87 initStoreSync sync.Once 88 storeSyncService *storeSyncService 89 monitor *transportMonitor 90 } 91 92 type MonitorEventListenerId int 93 94 type transportMonitor struct { 95 lock sync.RWMutex 96 listenersByType map[MonitorEventType]map[MonitorEventListenerId]MonitorEventHandler 97 listenersForAllEvents map[MonitorEventListenerId]MonitorEventHandler 98 subId MonitorEventListenerId 99 } 100 101 func newMonitor() *transportMonitor { 102 return &transportMonitor{ 103 listenersByType: make(map[MonitorEventType]map[MonitorEventListenerId]MonitorEventHandler), 104 listenersForAllEvents: make(map[MonitorEventListenerId]MonitorEventHandler), 105 } 106 } 107 108 func (m *transportMonitor) addListener(listener MonitorEventHandler, eventTypes []MonitorEventType) MonitorEventListenerId { 109 m.lock.Lock() 110 defer m.lock.Unlock() 111 112 m.subId++ 113 if len(eventTypes) == 0 { 114 m.listenersForAllEvents[m.subId] = listener 115 } else { 116 for _, eventType := range eventTypes { 117 listeners, ok := m.listenersByType[eventType] 118 if !ok { 119 listeners = make(map[MonitorEventListenerId]MonitorEventHandler) 120 m.listenersByType[eventType] = listeners 121 } 122 listeners[m.subId] = listener 123 } 124 } 125 126 return m.subId 127 } 128 129 func (m *transportMonitor) removeListener(listenerId MonitorEventListenerId) { 130 m.lock.Lock() 131 defer m.lock.Unlock() 132 133 delete(m.listenersForAllEvents, listenerId) 134 for _, listeners := range m.listenersByType { 135 delete(listeners, listenerId) 136 } 137 } 138 139 func (m *transportMonitor) sendEvent(event *MonitorEvent) { 140 m.lock.RLock() 141 defer m.lock.RUnlock() 142 143 for _, l := range m.listenersForAllEvents { 144 l(event) 145 } 146 147 for _, l := range m.listenersByType[event.EventType] { 148 l(event) 149 } 150 } 151 152 func (bus *transportEventBus) GetId() *uuid.UUID { 153 return &bus.Id 154 } 155 156 func (bus *transportEventBus) init() { 157 bus.Id = uuid.New() 158 bus.storeManager = newStoreManager(bus) 159 bus.ChannelManager = NewBusChannelManager(bus) 160 bus.brokerConnections = make(map[*uuid.UUID]bridge.Connection) 161 bus.bc = bridge.NewBrokerConnector() 162 bus.monitor = newMonitor() 163 if enableLogging { 164 fmt.Printf("🌈 Transport booted with Id [%s]\n", bus.Id.String()) 165 } 166 } 167 168 func (bus *transportEventBus) GetStoreManager() StoreManager { 169 return bus.storeManager 170 } 171 172 // GetChannelManager Get a pointer to the ChannelManager for managing Channels. 173 func (bus *transportEventBus) GetChannelManager() ChannelManager { 174 return bus.ChannelManager 175 } 176 177 // SendResponseMessage Send a ResponseDir type (inbound) message on Channel, with supplied Payload. 178 // Throws error if the Channel does not exist. 179 func (bus *transportEventBus) SendResponseMessage(channelName string, payload interface{}, destId *uuid.UUID) error { 180 channelObject, err := bus.ChannelManager.GetChannel(channelName) 181 if err != nil { 182 return err 183 } 184 config := buildConfig(channelName, payload, destId) 185 message := model.GenerateResponse(config) 186 sendMessageToChannel(channelObject, message) 187 return nil 188 } 189 190 // SendBroadcastMessage sends the payload as an outbound broadcast message to channelName. Since it is a broadcast, 191 // the payload does not require a destination ID. Throws an error if the channel does not exist. 192 func (bus *transportEventBus) SendBroadcastMessage(channelName string, payload interface{}) error { 193 channelObject, err := bus.ChannelManager.GetChannel(channelName) 194 if err != nil { 195 return err 196 } 197 config := buildConfig(channelName, payload, nil) 198 message := model.GenerateResponse(config) 199 sendMessageToChannel(channelObject, message) 200 return nil 201 } 202 203 // SendRequestMessage Send a RequestDir type message (outbound) message on Channel, with supplied Payload. 204 // Throws error if the Channel does not exist. 205 func (bus *transportEventBus) SendRequestMessage(channelName string, payload interface{}, destId *uuid.UUID) error { 206 channelObject, err := bus.ChannelManager.GetChannel(channelName) 207 if err != nil { 208 return err 209 } 210 config := buildConfig(channelName, payload, destId) 211 message := model.GenerateRequest(config) 212 sendMessageToChannel(channelObject, message) 213 return nil 214 } 215 216 // SendErrorMessage Send a ErrorDir type message (outbound) message on Channel, with supplied error 217 // Throws error if the Channel does not exist. 218 func (bus *transportEventBus) SendErrorMessage(channelName string, err error, destId *uuid.UUID) error { 219 channelObject, chanErr := bus.ChannelManager.GetChannel(channelName) 220 if chanErr != nil { 221 return err 222 } 223 config := buildError(channelName, err, destId) 224 message := model.GenerateError(config) 225 sendMessageToChannel(channelObject, message) 226 return nil 227 } 228 229 // ListenStream Listen to stream of ResponseDir (inbound) messages on Channel. Will keep on ticking until closed. 230 // Returns MessageHandler 231 // // To close an open stream. 232 // handler, Err := bus.ListenStream("my-Channel") 233 // // ... 234 // handler.close() // this will close the stream. 235 func (bus *transportEventBus) ListenStream(channelName string) (MessageHandler, error) { 236 channel, err := getChannelFromManager(bus, channelName) 237 if err != nil { 238 return nil, err 239 } 240 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, true, false, nil, false) 241 return messageHandler, nil 242 } 243 244 // AddMonitorEventListener Adds new monitor event listener for the a given set of event types. 245 // If eventTypes param is not provided, the listener will be called for all events. 246 // Returns the id of the newly added event listener. 247 func (bus *transportEventBus) AddMonitorEventListener( 248 listener MonitorEventHandler, eventTypes ...MonitorEventType) MonitorEventListenerId { 249 250 return bus.monitor.addListener(listener, eventTypes) 251 } 252 253 // RemoveMonitorEventListener Removes a given event listener 254 func (bus *transportEventBus) RemoveMonitorEventListener(listenerId MonitorEventListenerId) { 255 bus.monitor.removeListener(listenerId) 256 } 257 258 // ListenStreamForDestination Listen to stream of ResponseDir (inbound) messages on Channel for a specific DestinationId. 259 // Will keep on ticking until closed, returns MessageHandler 260 // // To close an open stream. 261 // handler, Err := bus.ListenStream("my-Channel") 262 // // ... 263 // handler.close() // this will close the stream. 264 func (bus *transportEventBus) ListenStreamForDestination(channelName string, destId *uuid.UUID) (MessageHandler, error) { 265 channel, err := getChannelFromManager(bus, channelName) 266 if err != nil { 267 return nil, err 268 } 269 if destId == nil { 270 return nil, fmt.Errorf("DestinationId cannot be nil") 271 } 272 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, false, false, destId, false) 273 return messageHandler, nil 274 } 275 276 // ListenRequestStream Listen to a stream of RequestDir (outbound) messages on Channel. Will keep on ticking until closed. 277 // Returns MessageHandler 278 // // To close an open stream. 279 // handler, Err := bus.ListenRequestStream("my-Channel") 280 // // ... 281 // handler.close() // this will close the stream. 282 func (bus *transportEventBus) ListenRequestStream(channelName string) (MessageHandler, error) { 283 channel, err := getChannelFromManager(bus, channelName) 284 if err != nil { 285 return nil, err 286 } 287 messageHandler := bus.wrapMessageHandler(channel, model.RequestDir, true, false, nil, false) 288 return messageHandler, nil 289 } 290 291 // ListenRequestStreamForDestination Listen to a stream of RequestDir (outbound) messages on Channel for a specific DestinationId. 292 // Will keep on ticking until closed, returns MessageHandler 293 // // To close an open stream. 294 // handler, Err := bus.ListenRequestStream("my-Channel") 295 // // ... 296 // handler.close() // this will close the stream. 297 func (bus *transportEventBus) ListenRequestStreamForDestination( 298 channelName string, destId *uuid.UUID) (MessageHandler, error) { 299 300 channel, err := getChannelFromManager(bus, channelName) 301 if err != nil { 302 return nil, err 303 } 304 if destId == nil { 305 return nil, fmt.Errorf("DestinationId cannot be nil") 306 } 307 messageHandler := bus.wrapMessageHandler(channel, model.RequestDir, false, false, destId, false) 308 return messageHandler, nil 309 } 310 311 // ListenRequestOnce Listen for a single RequestDir (outbound) messages on Channel. Handler is closed after a single event. 312 // Returns MessageHandler 313 func (bus *transportEventBus) ListenRequestOnce(channelName string) (MessageHandler, error) { 314 channel, err := getChannelFromManager(bus, channelName) 315 if err != nil { 316 return nil, err 317 } 318 id := checkForSuppliedId(nil) 319 messageHandler := bus.wrapMessageHandler(channel, model.RequestDir, true, false, id, true) 320 return messageHandler, nil 321 } 322 323 // ListenRequestOnceForDestination Listen for a single RequestDir (outbound) messages on Channel with a specific DestinationId. 324 // Handler is closed after a single event, returns MessageHandler 325 func (bus *transportEventBus) ListenRequestOnceForDestination( 326 channelName string, destId *uuid.UUID) (MessageHandler, error) { 327 328 channel, err := getChannelFromManager(bus, channelName) 329 if err != nil { 330 return nil, err 331 } 332 if destId == nil { 333 return nil, fmt.Errorf("DestinationId cannot be nil") 334 } 335 messageHandler := bus.wrapMessageHandler(channel, model.RequestDir, false, false, destId, true) 336 return messageHandler, nil 337 } 338 339 // ListenFirehose pull in everything being fired on a channel. 340 func (bus *transportEventBus) ListenFirehose(channelName string) (MessageHandler, error) { 341 channel, err := getChannelFromManager(bus, channelName) 342 if err != nil { 343 return nil, err 344 } 345 messageHandler := bus.wrapMessageHandler(channel, model.RequestDir, true, true, nil, false) 346 return messageHandler, nil 347 } 348 349 // ListenOnce Will listen for a single ResponseDir message on the Channel before un-subscribing automatically. 350 func (bus *transportEventBus) ListenOnce(channelName string) (MessageHandler, error) { 351 channel, err := getChannelFromManager(bus, channelName) 352 if err != nil { 353 return nil, err 354 } 355 id := checkForSuppliedId(nil) 356 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, true, false, id, true) 357 return messageHandler, nil 358 } 359 360 // ListenOnceForDestination Will listen for a single ResponseDir message on the Channel before un-subscribing automatically. 361 func (bus *transportEventBus) ListenOnceForDestination(channelName string, destId *uuid.UUID) (MessageHandler, error) { 362 channel, err := getChannelFromManager(bus, channelName) 363 if err != nil { 364 return nil, err 365 } 366 if destId == nil { 367 return nil, fmt.Errorf("DestinationId cannot be nil") 368 } 369 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, false, false, destId, true) 370 return messageHandler, nil 371 } 372 373 // RequestOnce Send a request message with Payload and wait for and Handle a single response message. 374 // Returns MessageHandler or error if the Channel is unknown 375 func (bus *transportEventBus) RequestOnce(channelName string, payload interface{}) (MessageHandler, error) { 376 channel, err := getChannelFromManager(bus, channelName) 377 if err != nil { 378 return nil, err 379 } 380 destId := checkForSuppliedId(nil) 381 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, true, false, destId, true) 382 config := buildConfig(channelName, payload, destId) 383 message := model.GenerateRequest(config) 384 messageHandler.requestMessage = message 385 return messageHandler, nil 386 } 387 388 // RequestOnceForDestination Send a request message with Payload and wait for and Handle a single response message for a targeted DestinationId 389 // Returns MessageHandler or error if the Channel is unknown 390 func (bus *transportEventBus) RequestOnceForDestination( 391 channelName string, payload interface{}, destId *uuid.UUID) (MessageHandler, error) { 392 393 channel, err := getChannelFromManager(bus, channelName) 394 if err != nil { 395 return nil, err 396 } 397 if destId == nil { 398 return nil, fmt.Errorf("DestinationId cannot be nil") 399 } 400 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, false, false, destId, true) 401 config := buildConfig(channelName, payload, destId) 402 message := model.GenerateRequest(config) 403 messageHandler.requestMessage = message 404 return messageHandler, nil 405 } 406 407 func getChannelFromManager(bus *transportEventBus, channelName string) (*Channel, error) { 408 channelManager := bus.ChannelManager 409 channel, err := channelManager.GetChannel(channelName) 410 return channel, err 411 } 412 413 // RequestStream Send a request message with Payload and wait for and Handle all response messages. 414 // Returns MessageHandler or error if Channel is unknown 415 func (bus *transportEventBus) RequestStream(channelName string, payload interface{}) (MessageHandler, error) { 416 channel, err := getChannelFromManager(bus, channelName) 417 if err != nil { 418 return nil, err 419 } 420 id := checkForSuppliedId(nil) 421 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, true, false, id, false) 422 config := buildConfig(channelName, payload, id) 423 message := model.GenerateRequest(config) 424 messageHandler.requestMessage = message 425 return messageHandler, nil 426 } 427 428 // RequestStreamForDestination Send a request message with Payload and wait for and Handle all response messages with a supplied DestinationId 429 // Returns MessageHandler or error if Channel is unknown 430 func (bus *transportEventBus) RequestStreamForDestination( 431 channelName string, payload interface{}, destId *uuid.UUID) (MessageHandler, error) { 432 433 channel, err := getChannelFromManager(bus, channelName) 434 if err != nil { 435 return nil, err 436 } 437 if destId == nil { 438 return nil, fmt.Errorf("DestinationId cannot be nil") 439 } 440 messageHandler := bus.wrapMessageHandler(channel, model.ResponseDir, false, false, destId, false) 441 config := buildConfig(channelName, payload, destId) 442 message := model.GenerateRequest(config) 443 messageHandler.requestMessage = message 444 return messageHandler, nil 445 } 446 447 // ConnectBroker Connect to a message broker. If successful, you get a pointer to a Connection. If not, you will get an error. 448 func (bus *transportEventBus) ConnectBroker(config *bridge.BrokerConnectorConfig) (conn bridge.Connection, err error) { 449 conn, err = bus.bc.Connect(config, enableLogging) 450 if conn != nil { 451 bus.brokerConnections[conn.GetId()] = conn 452 } 453 return 454 } 455 456 // Start a new Fabric Endpoint 457 func (bus *transportEventBus) StartFabricEndpoint( 458 connectionListener stompserver.RawConnectionListener, config EndpointConfig) error { 459 460 if bus.fabEndpoint != nil { 461 return fmt.Errorf("unable to start: fabric endpoint is already running") 462 } 463 if configErr := config.validate(); configErr != nil { 464 return configErr 465 } 466 467 // start the store sync service the first time a fabric endpoint 468 // is started. 469 bus.initStoreSync.Do(func() { 470 bus.storeSyncService = newStoreSyncService(bus) 471 }) 472 473 bus.fabEndpoint = newFabricEndpoint(bus, connectionListener, config) 474 bus.fabEndpoint.Start() 475 return nil 476 } 477 478 func (bus *transportEventBus) StopFabricEndpoint() error { 479 fe := bus.fabEndpoint 480 if fe == nil { 481 return fmt.Errorf("unable to stop: fabric endpoint is not running") 482 } 483 bus.fabEndpoint = nil 484 fe.Stop() 485 return nil 486 } 487 488 func (bus *transportEventBus) CreateAsyncTransaction() BusTransaction { 489 return newBusTransaction(bus, asyncTransaction) 490 } 491 492 func (bus *transportEventBus) CreateSyncTransaction() BusTransaction { 493 return newBusTransaction(bus, syncTransaction) 494 } 495 496 func (bus *transportEventBus) SendMonitorEvent( 497 evtType MonitorEventType, entityName string, payload interface{}) { 498 499 bus.monitor.sendEvent(NewMonitorEvent(evtType, entityName, payload)) 500 } 501 502 func (bus *transportEventBus) wrapMessageHandler( 503 channel *Channel, direction model.Direction, ignoreId bool, allTraffic bool, destId *uuid.UUID, 504 runOnce bool) *messageHandler { 505 506 messageHandler := createMessageHandler(channel, destId, bus.ChannelManager) 507 messageHandler.ignoreId = ignoreId 508 509 if runOnce { 510 messageHandler.invokeOnce = &sync.Once{} 511 } 512 513 errorHandler := func(err error) { 514 if messageHandler.errorHandler != nil { 515 if runOnce { 516 messageHandler.invokeOnce.Do(func() { 517 atomic.AddInt64(&messageHandler.runCount, 1) 518 messageHandler.errorHandler(err) 519 520 bus.GetChannelManager().UnsubscribeChannelHandler( 521 channel.Name, messageHandler.subscriptionId) 522 }) 523 } else { 524 atomic.AddInt64(&messageHandler.runCount, 1) 525 messageHandler.errorHandler(err) 526 } 527 } 528 } 529 successHandler := func(msg *model.Message) { 530 if messageHandler.successHandler != nil { 531 if runOnce { 532 messageHandler.invokeOnce.Do(func() { 533 atomic.AddInt64(&messageHandler.runCount, 1) 534 messageHandler.successHandler(msg) 535 536 bus.GetChannelManager().UnsubscribeChannelHandler( 537 channel.Name, messageHandler.subscriptionId) 538 }) 539 } else { 540 atomic.AddInt64(&messageHandler.runCount, 1) 541 messageHandler.successHandler(msg) 542 } 543 } 544 } 545 546 handlerWrapper := func(msg *model.Message) { 547 dir := direction 548 id := messageHandler.destination 549 if allTraffic { 550 if msg.Direction == model.ErrorDir { 551 errorHandler(msg.Error) 552 } else { 553 successHandler(msg) 554 } 555 } else { 556 if msg.Direction == dir { 557 // if we're checking for specific traffic, check a DestinationId match is required. 558 if !messageHandler.ignoreId && 559 (msg.DestinationId != nil && id != nil) && (id.String() == msg.DestinationId.String()) { 560 successHandler(msg) 561 } 562 if messageHandler.ignoreId { 563 successHandler(msg) 564 } 565 } 566 if msg.Direction == model.ErrorDir { 567 errorHandler(msg.Error) 568 } 569 } 570 } 571 572 messageHandler.wrapperFunction = handlerWrapper 573 return messageHandler 574 } 575 576 func checkForSuppliedId(id *uuid.UUID) *uuid.UUID { 577 if id == nil { 578 i := uuid.New() 579 id = &i 580 } 581 return id 582 } 583 584 func sendMessageToChannel(channelObject *Channel, message *model.Message) { 585 channelObject.Send(message) 586 } 587 588 func buildConfig(channelName string, payload interface{}, destinationId *uuid.UUID) *model.MessageConfig { 589 config := new(model.MessageConfig) 590 id := uuid.New() 591 config.Id = &id 592 config.DestinationId = destinationId 593 config.Channel = channelName 594 config.Payload = payload 595 return config 596 } 597 598 func buildError(channelName string, err error, destinationId *uuid.UUID) *model.MessageConfig { 599 config := new(model.MessageConfig) 600 id := uuid.New() 601 config.Id = &id 602 config.DestinationId = destinationId 603 config.Channel = channelName 604 config.Err = err 605 return config 606 } 607 608 func createMessageHandler(channel *Channel, destinationId *uuid.UUID, channelMgr ChannelManager) *messageHandler { 609 messageHandler := new(messageHandler) 610 messageHandler.channel = channel 611 id := uuid.New() 612 messageHandler.id = &id 613 messageHandler.destination = destinationId 614 messageHandler.channelManager = channelMgr 615 return messageHandler 616 }