francois2metz / em-eventsource

em-eventsource is an eventmachine library to consume Server-Sent Events streaming API.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getting disconnected -- is it the server's problem?

ramontayag opened this issue · comments

I'm not very familiar with SSE and where to look for the reasons behind disconnections. I'm trying to connect to https://horizon.stellar.org/operations:

Modifying examples/simple.rb:

require 'em-eventsource'

EM.run do
  source = EM::EventSource.new("https://horizon.stellar.org/operations")
  source.retry = 3

  source.message do |message|
    puts "new message #{message}"
    # puts "New Message"
  end

  source.error do |error|
    puts "error #{error}"
  end

  source.start
end

It disconnects immediately, and then retries 1 second later (the server has a retry header of 1000).

Mind pointing me to the right direction to figure out why it's getting disconnected?

It seems to be the server. I tried using a browser, and the server also close the connection immediately.

Thanks - I'll close this. Mind sharing what you use to test it?

I used the standard EventSource object available in the brower.

const es = new EventSource('https://horizon.stellar.org/operations');
es.addEventListener('open', () => {
  console.log('opened')
});
es.addEventListener('message', e => {
 console.log(e)
});
es.addEventListener('error', (event) => {
  console.log(event);
});

Got it thanks

I used the standard EventSource object available in the brower.

const es = new EventSource('https://horizon.stellar.org/operations');
es.addEventListener('open', () => {
  console.log('opened')
});
es.addEventListener('message', e => {
 console.log(e)
});
es.addEventListener('error', (event) => {
  console.log(event);
});

@francois2metz Sorry, this might be a dumb question, but what is the difference between using your library and the EventSource object you noted in the last reply.

I'm a bit confused about how to start a stream asynchronously such that my console window isn't hogged by the stream outputs. Following from that, then I'd like to be able to check the stream connection status with source.ready_state as noted in your readme. I don't completely understand but, when you start the stream, its an infinite loop and never returns an object?

Here's the basic code im using:

def subscribe_to_sse
    source = EventMachine::EventSource.new(@url, query = {},
                                          headers = {
                                            'Authorization' => "Bearer #{token}",
                                            'Accept' => 'text/event-stream',
                                            'Cache-Control' => 'no-cache'})
    EM.run do
      source.retry = 5
      source.open do
        puts 'Opened connection...'
      end
      source.on "open" do |message|
        puts message
      end

      source.on "put" do |message|
        puts message
      end

      source.on "keep-alive" do
        puts "Keep Alive message..."
      end

      source.error do |error|
        puts "Error: #{error}"
      end

      source.message do |message|
        puts message
      end
      source.start
    end
  end

Hi @DriftingShadows, The difference between my snippet above and this library is the language. The browser expose a native (except Edge) EventSource in javascript. This library implement almost the same API in ruby with eventmachine.

To check the status, you can either check it after some time with EM.add_timer or in the callbacks provided (open or error for instance).

Thank you @francois2metz . Your response is really helpful. I should have realised earlier they were indeed in different languages.

I have just one more question which might be a bit off topic. If I wanted to start multiple concurrent streams (for eg. One for each user) how would I go about doing this? I was thinking maybe doing async sidekiq background jobs but perhaps there are other better ways. Thanks for any help.

You can use event machine and this library to start has many streams as you want at the same time.

How would I keep track of the streams though? I would need to detect any streams that stop for some reason and restart it. Also are there any considerations resource usage like the number of threads being used?

EDIT: Just to make it more clear. Say for example I have a user that adds a third party device (eg. a nest thermostat) to our platform. I would then start a stream for that device from the Nest servers using its access token. Then if the user decides to delete that device from our platform and add a different one with a different access token. I would have to close the original stream and open a new one. The question is, how would I close the old stream?

Hi @DriftingShadows This library provide the basis to do what you need. You can close a steam and start and a new one without problems.
Still I would like to not transform this issue as a forum. Feel free to ask your questions on stack overflow.

Yep sounds good. Thanks for the help.