func (sender *Sender) sendStartMessage(startMessage models.PendingStartMessage) { messageToSend, shouldSend := sender.startMessageToSend(startMessage) if shouldSend { if sender.numberOfStartMessagesSent < sender.conf.SenderMessageLimit { sender.logger.Info("Sending message", startMessage.LogDescription()) err := sender.messageBus.Publish(sender.conf.SenderNatsStartSubject, messageToSend.ToJSON()) if err != nil { sender.logger.Error("Failed to send start message", err, startMessage.LogDescription()) sender.didSucceed = false return } sender.sentStartMessages = append(sender.sentStartMessages, startMessage) if startMessage.KeepAlive == 0 { sender.queueStartMessageForDeletion(startMessage, "a sent start message with no keep alive") } else { sender.markStartMessageSent(startMessage) } sender.numberOfStartMessagesSent += 1 } } else { sender.queueStartMessageForDeletion(startMessage, "start message that will not be sent") } }
func (a *appAnalyzer) appendStartMessageIfNotDuplicate(message models.PendingStartMessage, loggingMessage string, additionalDetails map[string]string) (didAppend bool) { existingMessage, alreadyQueued := a.existingPendingStartMessages[message.StoreKey()] if !alreadyQueued { a.logger.Info(fmt.Sprintf("Enqueuing Start Message: %s", loggingMessage), message.LogDescription(), additionalDetails) a.startMessages[message.StoreKey()] = message return true } else { a.logger.Info(fmt.Sprintf("Skipping Already Enqueued Start Message: %s", loggingMessage), existingMessage.LogDescription(), additionalDetails) return false } }
func (sender *Sender) startMessageToSend(message models.PendingStartMessage) (models.StartMessage, bool) { messageToSend := models.StartMessage{ MessageId: message.MessageId, AppGuid: message.AppGuid, AppVersion: message.AppVersion, InstanceIndex: message.IndexToStart, } if message.SkipVerification { sender.logger.Info("Sending start message: message is marked with SkipVerification", message.LogDescription()) return messageToSend, true } appKey := sender.store.AppKey(message.AppGuid, message.AppVersion) app, found := sender.apps[appKey] if !found { sender.logger.Info("Skipping sending start message: app is no longer desired", message.LogDescription()) return models.StartMessage{}, false } if !app.IsDesired() { sender.logger.Info("Skipping sending start message: app is no longer desired", message.LogDescription(), app.LogDescription()) return models.StartMessage{}, false } if !app.IsIndexDesired(message.IndexToStart) { sender.logger.Info("Skipping sending start message: instance index is beyond the desired # of instances", message.LogDescription(), app.LogDescription()) return models.StartMessage{}, false } if app.HasStartingOrRunningInstanceAtIndex(message.IndexToStart) { sender.logger.Info("Skipping sending start message: instance is already running", message.LogDescription(), app.LogDescription()) return models.StartMessage{}, false } sender.logger.Info("Sending start message: instance is not running at desired index", message.LogDescription(), app.LogDescription()) return messageToSend, true }
func (sender *Sender) queueStartMessageForDeletion(startMessage models.PendingStartMessage, reason string) { sender.logger.Info(fmt.Sprintf("Deleting %s", reason), startMessage.LogDescription()) sender.startMessagesToDelete = append(sender.startMessagesToDelete, startMessage) }
func (sender *Sender) markStartMessageSent(startMessage models.PendingStartMessage) { startMessage.SentOn = sender.timeProvider.Time().Unix() sender.startMessagesToSave = append(sender.startMessagesToSave, startMessage) }
func (sender *Sender) markStartMessageSent(startMessage models.PendingStartMessage) { startMessage.SentOn = sender.currentTime.Unix() sender.startMessagesToSave = append(sender.startMessagesToSave, startMessage) }
"github.com/cloudfoundry/hm9000/models" . "github.com/cloudfoundry/hm9000/store" "github.com/cloudfoundry/hm9000/testhelpers/fakelogger" "github.com/cloudfoundry/storeadapter" "github.com/cloudfoundry/storeadapter/etcdstoreadapter" "github.com/cloudfoundry/storeadapter/storenodematchers" "github.com/cloudfoundry/storeadapter/workerpool" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Storing PendingStartMessages", func() { var ( store Store storeAdapter storeadapter.StoreAdapter conf *config.Config message1 models.PendingStartMessage message2 models.PendingStartMessage message3 models.PendingStartMessage ) BeforeEach(func() { var err error conf, err = config.DefaultConfig() Ω(err).ShouldNot(HaveOccurred()) storeAdapter = etcdstoreadapter.NewETCDStoreAdapter(etcdRunner.NodeURLS(), workerpool.NewWorkerPool(conf.StoreMaxConcurrentRequests)) err = storeAdapter.Connect() Ω(err).ShouldNot(HaveOccurred()) message1 = models.NewPendingStartMessage(time.Unix(100, 0), 10, 4, "ABC", "123", 1, 1.0, models.PendingStartMessageReasonInvalid) message2 = models.NewPendingStartMessage(time.Unix(100, 0), 10, 4, "DEF", "123", 1, 1.0, models.PendingStartMessageReasonInvalid) message3 = models.NewPendingStartMessage(time.Unix(100, 0), 10, 4, "ABC", "456", 1, 1.0, models.PendingStartMessageReasonInvalid)
}) }) Context("when there are no stop messages in the queue", func() { It("should not send any messages", func() { err := sender.Send() Ω(err).ShouldNot(HaveOccurred()) Ω(messageBus.PublishedMessages).Should(BeEmpty()) }) }) Context("when there are start messages", func() { var keepAliveTime int var sentOn int64 var err error var pendingMessage models.PendingStartMessage var storeSetErrInjector *fakestoreadapter.FakeStoreAdapterErrorInjector JustBeforeEach(func() { store.SyncDesiredState(app.DesiredState(1)) pendingMessage = models.NewPendingStartMessage(time.Unix(100, 0), 30, keepAliveTime, app.AppGuid, app.AppVersion, 0, 1.0, models.PendingStartMessageReasonInvalid) pendingMessage.SentOn = sentOn store.SavePendingStartMessages( pendingMessage, ) storeAdapter.SetErrInjector = storeSetErrInjector err = sender.Send() }) BeforeEach(func() { keepAliveTime = 0