// BroadcastMessage broadcasts a guble-protocol-message to all the other nodes in the guble cluster func (cluster *Cluster) BroadcastMessage(pMessage *protocol.Message) error { logger.WithField("message", pMessage).Debug("BroadcastMessage") cMessage := &message{ NodeID: cluster.Config.ID, Type: gubleMessage, Body: pMessage.Bytes(), } return cluster.broadcastClusterMessage(cMessage) }
// StoreMessage is a part of the `store.MessageStore` implementation. func (dms *DummyMessageStore) StoreMessage(message *protocol.Message, nodeID uint8) (int, error) { partitionName := message.Path.Partition() nextID, ts, err := dms.GenerateNextMsgID(partitionName, 0) if err != nil { return 0, err } message.ID = nextID message.Time = ts message.NodeID = nodeID data := message.Bytes() if err := dms.Store(partitionName, nextID, data); err != nil { return 0, err } return len(data), nil }
// StoreMessage is a part of the `store.MessageStore` implementation. func (fms *FileMessageStore) StoreMessage(message *protocol.Message, nodeID uint8) (int, error) { partitionName := message.Path.Partition() // If nodeID is zero means we are running in standalone more, otherwise // if the message has no nodeID it means it was received by this node if nodeID == 0 || message.NodeID == 0 { id, ts, err := fms.GenerateNextMsgID(partitionName, nodeID) if err != nil { logger.WithError(err).Error("Generation of id failed") return 0, err } message.ID = id message.Time = ts message.NodeID = nodeID log.WithFields(log.Fields{ "generatedID": id, "generatedTime": message.Time, }).Debug("Locally generated ID for message") } data := message.Bytes() if err := fms.Store(partitionName, message.ID, message.Bytes()); err != nil { logger. WithError(err).WithField("partition", partitionName). Error("Error storing locally generated messagein partition") return 0, err } logger.WithFields(log.Fields{ "id": message.ID, "ts": message.Time, "partition": partitionName, "messageUserID": message.UserID, "nodeID": nodeID, }).Debug("Stored message") return len(data), nil }
// HandleMessage stores the message in the MessageStore(and gets a new ID for it if the message was created locally) // and then passes it to the internal channel, and asynchronously to the cluster (if available). func (router *router) HandleMessage(message *protocol.Message) error { logger.WithFields(log.Fields{ "userID": message.UserID, "path": message.Path}).Debug("HandleMessage") mTotalMessagesIncoming.Add(1) if err := router.isStopping(); err != nil { logger.WithError(err).Error("Router is stopping") return err } if !router.accessManager.IsAllowed(auth.WRITE, message.UserID, message.Path) { return &PermissionDeniedError{UserID: message.UserID, AccessType: auth.WRITE, Path: message.Path} } var nodeID uint8 if router.cluster != nil { nodeID = router.cluster.Config.ID } mTotalMessagesIncomingBytes.Add(int64(len(message.Bytes()))) size, err := router.messageStore.StoreMessage(message, nodeID) if err != nil { logger.WithError(err).Error("Error storing message") mTotalMessageStoreErrors.Add(1) return err } mTotalMessagesStoredBytes.Add(int64(size)) router.handleOverloadedChannel() router.handleC <- message if router.cluster != nil && message.NodeID == router.cluster.Config.ID { go router.cluster.BroadcastMessage(message) } return nil }