예제 #1
0
func (watcher *Watcher) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := watcher.logger.Session("watcher")
	logger.Info("starting")
	defer logger.Info("finished")

	var subscription events.EventSource
	subscriptionChan := make(chan events.EventSource, 1)
	go subscribeToEvents(logger, watcher.bbsClient, subscriptionChan)

	eventChan := make(chan models.Event, 1)
	nextErrCount := 0

	close(ready)
	logger.Info("started")

	for {
		select {
		case subscription = <-subscriptionChan:
			if subscription != nil {
				go nextEvent(logger, subscription, eventChan)
			} else {
				go subscribeToEvents(logger, watcher.bbsClient, subscriptionChan)
			}

		case event := <-eventChan:
			if event != nil {
				watcher.handleEvent(logger, event)
			} else {
				nextErrCount += 1
				if nextErrCount > 2 {
					nextErrCount = 0
					go subscribeToEvents(logger, watcher.bbsClient, subscriptionChan)
					break
				}
			}
			go nextEvent(logger, subscription, eventChan)

		case <-signals:
			logger.Info("stopping")
			err := subscription.Close()
			if err != nil {
				logger.Error("failed-closing-event-source", err)
			}
			return nil
		}
	}
}
예제 #2
0
		var event models.Event
		for {
			Eventually(eventChannel).Should(Receive(&event))
			if event.EventType() == models.EventTypeDesiredLRPRemoved {
				break
			}
		}
	})

	AfterEach(func() {
		Eventually(done).Should(BeClosed())
		ginkgomon.Kill(bbsProcess)
	})

	It("does not emit latency metrics", func() {
		eventSource.Close()

		timeout := time.After(50 * time.Millisecond)
		for {
			select {
			case envelope := <-testMetricsChan:
				if envelope.GetEventType() == sonde_events.Envelope_ValueMetric {
					Expect(*envelope.ValueMetric.Name).NotTo(Equal("RequestLatency"))
				}
			case <-timeout:
				return
			}
		}
	})

	It("emits request counting metrics", func() {
func (h *EventStreamHandler) EventStream(w http.ResponseWriter, req *http.Request) {
	logger := h.logger.Session("event-stream-handler")

	closeNotifier := w.(http.CloseNotifier).CloseNotify()
	sourceChan := make(chan events.EventSource)

	flusher := w.(http.Flusher)

	go func() {
		source, err := h.bbs.SubscribeToEvents()
		if err != nil {
			logger.Error("failed-to-subscribe-to-events", err)
			close(sourceChan)
			return
		}
		sourceChan <- source
	}()

	var source events.EventSource

	select {
	case source = <-sourceChan:
		if source == nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
	case <-closeNotifier:
		return
	}

	defer source.Close()

	go func() {
		<-closeNotifier
		source.Close()
	}()

	w.Header().Add("Content-Type", "text/event-stream; charset=utf-8")
	w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
	w.Header().Add("Connection", "keep-alive")

	w.WriteHeader(http.StatusOK)

	flusher.Flush()

	eventID := 0
	for {
		bbsEvent, err := source.Next()
		if err != nil {
			logger.Error("failed-to-get-next-event", err)
			return
		}

		event, err := NewEventFromBBS(bbsEvent)
		if err != nil {
			logger.Error("failed-to-marshal-event", err)
			return
		}
		payload, err := json.Marshal(event)
		if err != nil {
			logger.Error("failed-to-marshal-event", err)
			return
		}

		err = sse.Event{
			ID:   strconv.Itoa(eventID),
			Name: string(event.EventType()),
			Data: payload,
		}.Write(w)
		if err != nil {
			break
		}

		flusher.Flush()

		eventID++
	}
}