rethinkdb / horizon

Horizon is a realtime, open-source backend for JavaScript apps.
MIT License
6.78k stars 349 forks source link

Manually reconnecting the web client #772

Open lirbank opened 8 years ago

lirbank commented 8 years ago

Server version: 2.0.0-beta-7 Client version: 2.0.0-beta-7

Not sure if I am doing this the right way but I can't seem to reconnect to the server after a temporary disconnect. Even though the client can't reconnect on it own, it should be possible to reconnect manually without refreshing the browser. Am I missing something or does it not work?

I run the code below and then close the server and start it again.

Example client code:

let message = {
  text: "What a beautiful horizon!",
  datetime: new Date(),
  author: "@dalanmiller"
}

let horizon = Horizon();
let chat = horizon("messages");
let isConnected = false;
let handle;

document.addEventListener("DOMContentLoaded", function(event) {
  document.querySelector('button').addEventListener('click', e => {
    console.log('CLICK');
    chat.store(message);
  });

  chat.watch().subscribe(docs => console.log('DOCUMENTS', docs.length));

  horizon.status(s => {
    console.log('status', s);
  });

  horizon.onReady(s => {
    if (handle) {
      clearInterval(handle);
    }
  });

  horizon.onSocketError(e => {
    console.log('socket error', e);
    //horizon.disconnect();
    //horizon = null;

    handle = setInterval(() => {
      console.log('RECONNECTING');
      //horizon = Horizon();
      //horizon.connect();
      chat.watch().subscribe((docs) => {console.log(docs.map(e => e.text))});
    }, 10000);
  });
});

Console: image

lirbank commented 8 years ago

Please note, the production release 1.1.3 has the same issue (with slightly different error messages if I remember correctly).

deontologician commented 8 years ago

This is due to the statuses being implemented by a BehaviorSubject, which will replay old states. This is good if you want to ensure you don't miss any states, but it's bad if you ever want to get rid of them.

Right now I'd suggest not manually reconnecting by simply emitting the query again, since there is likely other state that's not being cleaned up. It's best for now to just create a new horizon instance

lirbank commented 8 years ago

Thanks! But how do I "just create a new horizon instance"? I tried a lot of things but only got it working again after a page reload...

Edit: (as you can see in my code I tried multiple ways to disconnect from horizon and recreate the instance again, but it didn't help)

lirbank commented 8 years ago

Oh, never mind, got it working!

I just forgot to re-init the collection chat = horizon("messages"); after I created the new instance. This works for now. Thanks!

deontologician commented 8 years ago

Actually, I'm going to try getting this into 2.0.0, since even if you can't seamlessly reconnect, the experience here of reconnecting and re-issuing your queries is pretty bad and most everyone is going to run into reconnection needs. I don't think it should be too hard to fix

lirbank commented 8 years ago

Put this together and it seems to work properly:

let horizon;
let chat;
let handle;
let message = {text: 'What a beautiful horizon!'};

let connect = function () {
  console.log('CONNECTING');

  horizon = Horizon();
  horizon.status(s => console.log('status', s));

  horizon.onReady(s => {
    if (handle) {
      clearInterval(handle);
      handle = null;
    }
  });

  horizon.onSocketError(e => {
    console.log('socket error', e);
    if (! handle) handle = setInterval(connect, 5000);
  });

  chat = horizon('messages');
  chat.watch().subscribe(docs => console.log('DOCUMENT COUNT', docs.length));
};

document.addEventListener('DOMContentLoaded', function(event) {
  // Init
  connect();

  document.querySelector('button').addEventListener('click', e => {
    console.log('CLICK');
    chat.store(message);
  });
});

EDIT:

1) But it will not work for React Native as the socket errors, etc, can't be caught properly. So will be awesome to have a fix for that.

2) Another related issue, it is very hard to restart the server when the client is trying to reconnect. The server crashes on start so I have to try multiple times before I get it up and running again - will post a separate issue about that.

deontologician commented 8 years ago

beautiful, thanks for the example code

deontologician commented 8 years ago

Alright, I've been working on this for 3 days, can't seem to figure out what's going on, so I'm bumping this to 2.x.x