Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Check if missed heartbeat synchronously before sending message #5134

Closed
wants to merge 8 commits into from

Conversation

tjenkinson
Copy link
Contributor

@tjenkinson tjenkinson commented Jul 15, 2024

Chrome (and maybe other browsers) will throttle setTimeout under certain conditions, causing them to slow down, and this breaks the heartbeat detection logic.

This fix means if a message is emitted when the connection should be considered expired (but the setTimeout hasn't fired yet), we close that socket and then buffer the message for the new connection. So now a message should never be sent over an expired connection.

This doesn't solve the problem of connections being detected as expired too late. I think that could be done separately.

The kind of change this PR does introduce

  • a bug fix
  • a new feature
  • an update to the documentation
  • a code change that improves performance
  • other

Current behavior

Check the repro on #5135

New behavior

  • When the next message is sent, the system will realise it's missed the heartbeat, create a new connection, and then the message will be sent over the new connection
  • So now a message will never be sent over a stale connection, and we're not depending on the heartbeat timeout to fire correctly when a page comes back to life (which doesn't happen when it's throttled)

Other information (e.g. related issues)

The reason that the heartbeat logic is not immediately closing the old connection when the page is woken up is due to chrome pausing the setTimeout that's used in the heartbeat logic. This PR doesn't fix that. I Think that could be handled separately.

#3507 (comment) is another fix related to throttled timers

Let me know if you think this makes sense and I'm happy to look into adding a test for it

Chrome (and maybe other browsers) will throttle `setTimeout` under certain conditions, causing them to slow down, and this breaks the heartbeat detection logic.

This fix means if a message is emitted when the connection should be considered expired (but the `setTimeout` hasn't fired yet), we close that socket and then buffer the message for the new connection. So now a message should never be sent over an expired connection.

This doesn't solve the problem of connections being detected as expired too late. I think that could be done separately.
@tjenkinson tjenkinson changed the title [WIP] fix: Check if missed heartbeat synchronously before sending message fix: Check if missed heartbeat synchronously before sending message Aug 9, 2024
@tjenkinson
Copy link
Contributor Author

Looking at CI maybe this needs to be 2 separate PR's?

darrachequesne pushed a commit that referenced this pull request Sep 18, 2024
When a laptop is suspended or a phone is locked, the timer that is used
to check the liveness of the connection is paused and is not able to
detect that the heartbeat has failed.

Previously, emitting a message after resuming the page would lose the
message. The status of the timer will now be checked before sending the
message, so that it gets buffered and sent upon reconnection.

Note: we could also have used the Page Visibility API or a custom
setTimeout() method based on setInterval(), but this would not be as
reliable as the current solution.

Reference: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

Related: #5135
@darrachequesne
Copy link
Member

Merged as 8adcfbf.

I've made some minor edits and added a few tests. Could you please check if everything makes sense?

@tjenkinson
Copy link
Contributor Author

Merged as 8adcfbf.

I've made some minor edits and added a few tests. Could you please check if everything makes sense?

Thanks! Just this one comment 8adcfbf#r146871962

@tjenkinson
Copy link
Contributor Author

Closing given merged in 8adcfbf 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants