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

✨ Add ping/pong #576

Merged
merged 1 commit into from
Sep 27, 2022
Merged

✨ Add ping/pong #576

merged 1 commit into from
Sep 27, 2022

Conversation

alecgibson
Copy link
Collaborator

@alecgibson alecgibson commented Sep 27, 2022

This change adds the ability for a client to send a "ping" to the server
and receive a "pong" response.

The motivation for this is that sometimes the socket underlying the
Connection may not reliably report its connection state (for example
if using a wrapper around a "vanilla" websocket that handles
reconnection).

The most bullet-proof way for a client to determine its connection state
is to actually make a request to the server and assert that it receives
a timely response.

The implementation of ping/pong is arguably a websocket concern,
especially since it's already defined by the spec. However, the
browser JavaScript WebSocket does not expose this functionality,
so we have to add our own ping/pong layer on top anyway.

It's also worth noting that consumers of this library can't easily
send their own ping messages down the socket, since ShareDB will
error for unknown messages.

Note that this change only adds the ability for a client to ping the
server, and not the other way around. This is because:

  • the Agent is not an Emitter, and emitting a pong on the
    Backend is pretty meaningless
  • server-side implementations of WebSockets, such as ws, do
    expose a ping API

@coveralls
Copy link

coveralls commented Sep 27, 2022

Coverage Status

Coverage increased (+0.01%) to 97.427% when pulling 56ac7a8 on ping-pong into 8b531be on master.

@alecgibson
Copy link
Collaborator Author

NB This would be a perfect candidate for a plugin: #337

@@ -476,6 +478,12 @@ Connection.prototype.send = function(message) {
this.socket.send(JSON.stringify(message));
};

Connection.prototype.ping = function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From discussion today - let's throw an error if the connection state is not connected.

This is to guard against a bunch of ping requests queueing up at the socket layer if the socket is currently disconnected or connecting, and having them suddenly flood the socket when eventually connected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — added ERR_CANNOT_PING_OFFLINE

This change adds the ability for a client to send a "ping" to the server
and receive a "pong" response.

The motivation for this is that sometimes the socket underlying the
`Connection` may not reliably report its connection state (for example
if using a wrapper around a "vanilla" websocket that handles
reconnection).

The most bullet-proof way for a client to determine its connection state
is to actually make a request to the server and assert that it receives
a timely response.

The implementation of ping/pong is arguably a websocket concern,
especially since it's already [defined by the spec][1]. However, the
browser JavaScript [`WebSocket`][2] does not expose this functionality,
so we have to add our own ping/pong layer on top anyway.

It's also worth noting that consumers of this library can't easily
send their own ping messages down the socket, since ShareDB will
[error][3] for unknown messages.

Note that this change only adds the ability for a client to ping the
server, and not the other way around. This is because:

 - the `Agent` is not an `Emitter`, and emitting a `pong` on the
   `Backend` is pretty meaningless
 - server-side implementations of WebSockets, such as `ws`, _do_
   [expose a `ping` API][4]

[1]: https://www.rfc-editor.org/rfc/rfc6455#section-5.5.2
[2]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
[3]: https://github.com/share/sharedb/blob/8b531bedf19860ffe0b37a3e1c8da7a32b5005bd/lib/agent.js#L451
[4]: https://github.com/websockets/ws/blob/966f9d47cd0ff5aa9db0b2aa262f9819d3f4d414/lib/websocket.js#L351
@alecgibson alecgibson merged commit 9157342 into master Sep 27, 2022
@alecgibson alecgibson deleted the ping-pong branch September 27, 2022 16:53
@curran
Copy link
Contributor

curran commented Sep 28, 2022

Very nice!

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.

4 participants