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  }