parse-community / Parse-SDK-JS

The JavaScript SDK for Parse Platform
https://parseplatform.org
Apache License 2.0
1.32k stars 596 forks source link

LiveQuery socket not reconnecting on resume from sleep in mobile #585

Closed dpatel20 closed 6 years ago

dpatel20 commented 6 years ago

I have created a Web App use the Parse backend which utilises Parse's LiveQuery (Websockets).

Whilst testing on mobile devices, I have noticed that after a long(ish) sleep the LiveQuery events don't seem to get through. Best as I can tell/understand, the browser is closing (?) the websocket.

Behind the scenes, I know the Parse JS SDK implements an exponential backoff automatic reconnect.

Is there a way to instantly auto connect on the browser window getting focus?

I tried a quick hack in the JS SDK as follows in the LiveQuery 'open' function

      if (firstTime) {
        $(window).on('focus', function () {
          console.log("Window got focus");
          this.attempts = 0;
          console.log(_this4.state)
          if (_this4.state !== CLIENT_STATE.CONNECTED)
            _this4._handleReconnect();
        });
        firstTime = false;
      }

However, this does not seem to work (at least not consistently). If I remove the check on the CONNECTED status, then it seems to work but then I end up with multiple sockets open (I know as I have a toast popup that is activated on live updates -- without the CONNECT check I get two popups instead of one). So, does that suggest that the Parse SDK is not aware the connection is broken? How I can I force a check?

dpatel20 commented 6 years ago

After debugging further, I've seen that the state is CONNECTED so I can only guess it has not yet updated its state. Javascript is running as my debug code fires on focus. I further tried doing a close and resubscribe:

_this4.socket.close();
_this4.resubscribe();

From this, I found that the close would not fire for exactly 1min (I output some timestamps to the HTML). I cannot find where this 1min timeout comes from...any ideas?

dpatel20 commented 6 years ago

I'm using this to log my findings...hope someone can help:

flovilmart commented 6 years ago

I’m not sure it is related to the JS SDK itself. Perhaps there are workarounds that we could implement. Also, where lis your parse-server deployed?

dpatel20 commented 6 years ago

I am using Back4App, Parse Server 2.7.1.

I agree, I don't think it is an issue with the SDK...I was just using the SDK to debug/hack to try to find a workaround.

flovilmart commented 6 years ago

Possibly also related to a seeverside connection configuration. Did you try with a pure JS websocker client without the parse JS SDK?

dpatel20 commented 6 years ago

I have contacted back4app for some help...awaiting further feedback.

I have no idea how to test with a JS websocket client...you mean use something like socket.io to connect to the Parse server and see if I get the same issue? Could you help as to how to do this?

dpatel20 commented 6 years ago

I'm starting to think it might be my phone or browser!!...not seen the issue on another phone and tablet.

flovilmart commented 6 years ago

@dpatel20 that's something to consider too :)

dpatel20 commented 6 years ago

@flovilmart Seems to be occurring in other browsers and devices (to different extents/frequencies) --- all Android based. With the original code (without my hacks), it eventually seems to kick back into life.

Any suggestions of how I can work around this (or reduce the time to reconnect)?

flovilmart commented 6 years ago

I’m not sure at this point. Is there littérature around the reconnections problems, like with socketIO or else?

dpatel20 commented 6 years ago

I have done some more testing and taken logcats on my Android phone and various debug messages added. I can see that the connection is actually closed and the reconnect mechanism kicks in. But then it sits in the 'open' (i.e. trying to re-open the socket) state as there is no network.

When I resume the device, it can take a few secs to reconnect but it does reconnect. I was testing fairly soon after unlocking and saw that it was missing the event. If I wait a few seconds and then fire the event, then all is good.

flovilmart commented 6 years ago

Ok, good to hear you have a proper explanation! On Jun. 22, 2018, 05:37 -0400, dpatel20 notifications@github.com, wrote:

I have done some more testing and taken logcats on my Android phone and various debug messages added. I can see that the connection is actually closed and the reconnect mechanism kicks in. But then it sits in the 'open' (i.e. trying to re-open the socket) state as there is no network. When I resume the device, it can take a few secs to reconnect but it does reconnect. I was testing fairly soon after unlocking and saw that it was missing the event. If I wait a few seconds and then fire the event, then all is good. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

dpatel20 commented 6 years ago

I should note that I had to reduce the backoff in generateInterval(). I changed it to be:

return Math.random() * k * 2000;

With the original setup I had a connection timeout error in the logcat.

flovilmart commented 6 years ago

@dpatel20 is the back off configuration worth an addition to the SDK so the issue can be worked around?

dpatel20 commented 6 years ago

Do you mean being able to pass your own backoff function to the SDK?

flovilmart commented 6 years ago

Yep somehow when you setup the liveQuery client

dpatel20 commented 6 years ago

Hmmm...I'm a bit concerned that maybe a lot more complicated than it first seems (at least to me).

The generateInterval() function is not part of the LiveQueryClient class. If it was, then maybe the generateInterval could be an option in the constructor. But then that seems like quite a change for an issue only I seem to have come across?!

flovilmart commented 6 years ago

Yeah perhaps, my concern is that you’re able to ship something that works, with a potential workaround

dpatel20 commented 6 years ago

Well, this is frustrating now...I've gone back to the original generateInterval() and no longer seeing the timeout issue. I need to do more testing to figure out what's going on. :(

flovilmart commented 6 years ago

Haha, indeed!

flovilmart commented 6 years ago

Should we close this one then? Feel free to reopen if needed

dpatel20 commented 6 years ago

Agreed...close for now. If I find why I got the timeout error mentioned above, then I'll reopen.