feat(sync): Check for websocket connectivity and retry if not connected.

Because the WebSockets do not offer a way to know when they failed to
connect, use a delay and check the state of the connection.
This commit is contained in:
Alexis Métaireau 2024-10-25 16:18:49 +02:00
parent b7ca961912
commit 4ba5bbc542
No known key found for this signature in database
GPG key ID: 1C21B876828E5FF2
4 changed files with 17 additions and 3 deletions

View file

@ -70,6 +70,7 @@ export class SyncEngine {
* Authenticate with the server and start the transport layer.
*/
async authenticate() {
console.log("authenticating")
const [response, _, error] = await this._server.get(this._websocketTokenURI)
if (!error) {
this.start(response.token)

View file

@ -1,5 +1,6 @@
const PONG_TIMEOUT = 5000;
const PING_INTERVAL = 30000;
const FIRST_CONNECTION_TIMEOUT = 2000;
export class WebSocketTransport {
constructor(webSocketURI, authToken, messagesReceiver) {
@ -21,6 +22,13 @@ export class WebSocketTransport {
}
}
this.ensureOpen = setInterval(() => {
if (this.websocket.readyState !== WebSocket.OPEN) {
this.websocket.close()
clearInterval(this.ensureOpen)
}
}, FIRST_CONNECTION_TIMEOUT)
// To ensure the connection is still alive, we send ping and expect pong back.
// Websocket provides a `ping` method to keep the connection alive, but it's
// unfortunately not possible to access it from the WebSocket object.

View file

@ -236,12 +236,14 @@ U.Map = L.Map.extend({
},
render: function (fields) {
console.log("sync.websocketConnected", this.sync.websocketConnected)
console.log("options.syncEnabled", this.options.syncEnabled)
if (this.options.syncEnabled === true) {
if (!this.sync.websocketConnected) {
if (this.sync.websocketConnected !== true) {
const template = `
<h3><i class="icon icon-16"></i><span>${L._('Disconnected')}</span></h3>
<p>
${L._('This map has enabled real-time synchronization with other users, but you are currently disconnected. It will automatically reconnect when ready.')}
${L._('This map has enabled real-time synchronization with other users, but you are currently disconnected.It will automatically reconnect when ready.')}
</p>
`
this.dialog.open({

View file

@ -196,4 +196,7 @@ def run(host: str, port: int):
logging.debug(f"Waiting for connections on {host}:{port}")
await asyncio.Future() # run forever
asyncio.run(_serve())
try:
asyncio.run(_serve())
except KeyboardInterrupt:
print("Closing WebSocket server")