pusher / pusher-js

Pusher Javascript library
http://pusher.com
MIT License
2.11k stars 374 forks source link

Constant connection state changes when using other than ws transports #802

Open apostrofix opened 9 months ago

apostrofix commented 9 months ago

Do you want to request a feature or report a bug? Possibly report a bug.

What is the current behavior? When using other transports than web sockets, e.g. xhr_polling, the state_change event keeps firing and keeps toggling between connecting and connected states. That probably makes sense given the nature of the polling mechanism. However, what would be the proper way to then check if there is a successful connection?

p.s. I am not intentionally trying to use xhr_polling, I rely on the default config which switches to xhr_polling in case if ws is unavailable.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.

const pusherOptions: Options = {
  cluster,
  authEndpoint,
  auth: { headers: { Authorization: authorization } },
  enabledTransports: [ 'xhr_polling', 'xhr_streaming',  ], // only hardcoding it for testing purposes but in reality this is not set and uses default
};

pusherConnection = new Pusher(apiKey, pusherOptions);

pusherConnection.connection.bind('state_change', (context: any) => {
  console.log('STATE_CHANGE -> ', context); // this keeps changing from connecting to connected, and so on.
});

setInterval(() => {
 console.log('STATE -> ', pusherConnection.connection.state); // the state here seems to be kept as `connected` even while using `xhr_polling`
}, 1000);

What is the expected behavior? Have a way to reliably detect connection state changes that doesn't change every second. Imagine you want to react to a not connected state, it's quite difficult when the state changes constantly.

Checking for pusherConnection.connection.state directly seems to work, however I have to query it manually. Is that the better way or is there a bug with state_change?

Which versions of Pusher, and which browsers / OS are affected by this issue? Did this work in previous versions of Pusher? If so, which?

^8.0.1 (tried with 8.3.0 directly too)

benw-pusher commented 9 months ago

I'm not seeing the same behaviour here. Typically state changes would be a result of network conditions - do you see the same behaviour if you use a different device/network? Do you see the same behaviour if you use test.pusher.com?

apostrofix commented 9 months ago

Yes, I tried both - different devices and different network. The network is stable, I don't see any issues that could be causing it.

Here is a screenshot of the console logs from the example above: Screenshot 2024-02-14 at 20 07 39

Opening test.pusher.com in the browser (not sure if I can connect via a test app) looks fine. I get connected once and it stays connected.

apostrofix commented 9 months ago

I was able to pinpoint it to the activityTimeout option. I am sorry my example in the original post wasn't 100% complete. I thought the timeouts would be irrelevant. My config actually also sets the activityTimeout and pongTimeout to the options too.

const pusherOptions: Options = {
  activityTimeout: 5000, // 5 seconds - this is what causes the reconnects
  pongTimeout: 5000, // 5 seconds
  cluster,
  authEndpoint,
  auth: { headers: { Authorization: authorization } },
  enabledTransports: [ 'xhr_polling' ],
};

Removing the activity timeout fixes the issue. Having it set to 5 seconds (also 20 seconds) results in the reconnects. Changing it to 25 seconds seems like it's enough and the reconnects don't happen anymore, however our thinking was that 25 seconds gets dangerously close to 30s which we would like to avoid, since some firewalls kill inactive ws connections after 30s.

According to the docs, a shorter activityTimeout might cause unnecessary traffic. Is there a bug that might be causing the reconnects despite the unnecessary traffic or am I missing something?