4
votes

I am building live event streaming app (e.g. stock rates) using Spring Web Flux Reactive, MongoDB and Angular. I want to build following pipeline: MongoDB -> Reactive MongoDB Driver -> Spring Web Reactive MongoDB Repository -> Spring Web Reactive Controller -> Angular (through Server Sent Events).

Here is my Spring Web Reactive Controller:

@GetMapping(value = "/test", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<LiveRate> test() {
    Flux<LiveRate> res = liveRateRepository.findByLastUpdate(1504580678).log(); // I query hard-coded value and MongoDB returns 4 events

    return res;
}

Here is my Angular code:

var source = new EventSource('http://localhost:8080/test');
source.addEventListener('message', function(e) {
    console.log(e.data);
}, false);

For some reason Angular returns 4 events infinite number of times, also Spring keeps querying MongoDB. My understanding it that with Server Sent Events approach Spring should return all events it has and keep waiting for new ones, but instead looks like Angular keeps asking for more and more events.

If I hit http://localhost:8080/test in Browser it returns only 4 events as expected.

Could you please explain what I am missing? Thanks.

1

1 Answers

5
votes

My best guess here is that:

  1. the browser connects to the SSE stream, which triggers the repository query
  2. once all 4 entries have been retrieved, the Flux is completed by the repository
  3. this completes the SSE stream
  4. the browser reconnects automatically to the SSE source
  5. back to step number 1

You should see the browser reconnecting in your browser devtools (network tab).

If you're looking for an infinite stream, you should use the Tailable Cursors feature in Spring Data MongoDB. In your case, just annotating your repository method with @Tailable should do the trick.