From 04aef1b6095c351dc407b13a4553b0160a092f71 Mon Sep 17 00:00:00 2001 From: Terkwood <38859656+Terkwood@users.noreply.github.com> Date: Sun, 14 Jul 2019 18:10:55 -0400 Subject: [PATCH] Reconnect websocket automatically (#11) * Reconnect websocket automagically * clean up logs * remove hardcoded board --- package.json | 1 + src/modules/shims/gtp.js | 104 ++++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 78ba23c75..a0e9b2db4 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "preact": "^8.4.2", "react-markdown": "^3.6.0", "remark-breaks": "^1.0.1", + "robust-websocket": "^1.0.0", "uuid": "^3.3.2" }, "devDependencies": { diff --git a/src/modules/shims/gtp.js b/src/modules/shims/gtp.js index 81ee52f7b..5f85eb086 100644 --- a/src/modules/shims/gtp.js +++ b/src/modules/shims/gtp.js @@ -2,6 +2,7 @@ const EventEmitter = require('events') const Board = require('../board') +const RobustWebSocket = require('robust-websocket') const uuidv4 = require('uuid/v4') const GATEWAY_HOST_LOCAL = "ws://localhost:3012/gateway" @@ -83,33 +84,47 @@ class WebSocketController extends EventEmitter { // TODO BUGOUT don't hardcode this this.board = new Board(19,19) this.webSocketAddress = webSocketAddress - this.webSocket = new WebSocket(webSocketAddress) + this.webSocket = new RobustWebSocket(webSocketAddress) // manually ping the websocket every once in a while this.beeping = true this.beepTimeMs = 12625 setTimeout(() => this.beep(), this.beepTimeMs) - this.webSocket.onclose = event => { - console.log("websocket closed") - } + this.webSocket.addEventListener('close', event => { + console.log("WebSocket closed.") + }) - this.webSocket.onerror = event => { - console.log(`websocket error ${JSON.stringify(event)}`) - } + this.webSocket.addEventListener('error',event => { + console.log(`WebSocket error ${JSON.stringify(event)}`) + }) this.gameId = null this.gatewayConn = new GatewayConn(this.webSocket) - this.webSocket.onopen = _event => { - this.gatewayConn.requestGameId() - .then((reply, err) => { - if (!err) { - this.gameId = reply.gameId - } else { - console.log('FATAL ERROR - WE DO NOT HAVE A GAME ID') - } - }) - } + this.webSocket.addEventListener('open', () => { + if (!this.gameId) { + this.gatewayConn + .requestGameId() + .then((reply, err) => { + if (!err) { + this.gameId = reply.gameId + } else { + console.log('FATAL ERROR - WE DO NOT HAVE A GAME ID') + } + }) + } else { + this.gatewayConn + .reconnect(this.gameId, this.resolveMoveMade, this.board) + .then((rc, err) => { + console.log("Reconnected!") + }) + } + }) + + // reconnect event + this.webSocket.addEventListener('connecting', () => { + console.log('Reconnecting...') + }) } @@ -133,10 +148,12 @@ class WebSocketController extends EventEmitter { "coord": {"x":vertex[0],"y":vertex[1]} } - this.webSocket.onmessage = event => { + + this.webSocket.addEventListener('message', event => { try { let msg = JSON.parse(event.data) if (msg.type === "MoveMade" && msg.replyTo === makeMove.reqId) { + this.resolveMoveMade = undefined resolve({id: null, error: false}) } @@ -146,11 +163,12 @@ class WebSocketController extends EventEmitter { console.log(`Error processing websocket message: ${JSON.stringify(err)}`) resolve({ok: false}) } - } + }) this.webSocket.send(JSON.stringify(makeMove)) } else if (command.name === "genmove") { - this.webSocket.onmessage = event => { + this.resolveMoveMade = resolve + this.webSocket.addEventListener('message', event => { try { let msg = JSON.parse(event.data) if (msg.type === "MoveMade" && msg.player === letterToPlayer(command.args[0])) { @@ -164,7 +182,7 @@ class WebSocketController extends EventEmitter { console.log(`Error processing websocket message: ${JSON.stringify(err)}`) resolve({"id": null, "content": "", "error": true}) } - } + }) } else { resolve(true) @@ -202,6 +220,46 @@ class GatewayConn { this.webSocket = webSocket } + + async reconnect(gameId, resolveMoveMade, board) { + console.log("gatewayconn reconnect") + return new Promise((resolve, reject) => { + try { + let reconnectCommand = { + "type":"Reconnect", + "gameId": gameId, + "reqId": uuidv4() + } + + console.log(`sending ${JSON.stringify(reconnectCommand)}`) + this.webSocket.onmessage = event => { + try { + let msg = JSON.parse(event.data) + console.log(`message after reconnect: ${event.data}`) + if (msg.type === "Reconnected") { + resolve() + } + + if (resolveMoveMade && msg.type == "MoveMade") { + let sabakiCoord = board.vertex2coord([msg.coord.x, msg.coord.y]) + console.log("MOVE MADE ON RECONNECT") + resolveMoveMade({"id":null,"content":sabakiCoord,"error":false}) + } + + // discard any other messages + } catch (err) { + console.log(`Error processing websocket message: ${JSON.stringify(err)}`) + resolve({error: true}) + } + } + this.webSocket.send(JSON.stringify(reconnectCommand)) + resolve() + } catch (err) { + reject(err) + } + }) + } + async requestGameId() { return new Promise((resolve, reject) => { let requestGameId = { @@ -209,7 +267,7 @@ class GatewayConn { "reqId": uuidv4() } - this.webSocket.onmessage = event => { + this.webSocket.addEventListener('message', event => { try { let msg = JSON.parse(event.data) console.log(`incoming data ${event.data}`) @@ -221,7 +279,7 @@ class GatewayConn { console.log(`Error processing websocket message: ${JSON.stringify(err)}`) reject() } - } + }) this.webSocket.send(JSON.stringify(requestGameId)) })