From fd29928a9c65195345e6794c4347c0a884d4e40d Mon Sep 17 00:00:00 2001 From: Shuanglei Tao Date: Fri, 5 Jul 2019 22:32:01 +0800 Subject: [PATCH] html: retry websocket connection with exponential backoff --- html/package.json | 1 + html/src/components/terminal/index.tsx | 19 +++++++++++++++++++ html/yarn.lock | 12 ++++++++++++ src/index.html | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/html/package.json b/html/package.json index ac61c82..09d62b4 100644 --- a/html/package.json +++ b/html/package.json @@ -58,6 +58,7 @@ "webpack-merge": "^4.2.1" }, "dependencies": { + "backoff": "^2.5.0", "decko": "^1.2.0", "preact": "^8.4.2", "xterm": "^3.14.4", diff --git a/html/src/components/terminal/index.tsx b/html/src/components/terminal/index.tsx index b7c430b..909f740 100644 --- a/html/src/components/terminal/index.tsx +++ b/html/src/components/terminal/index.tsx @@ -1,4 +1,5 @@ import { bind } from 'decko'; +import * as backoff from 'backoff'; import { Component, h } from 'preact'; import { ITerminalOptions, Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; @@ -45,6 +46,7 @@ export class Xterm extends Component { private title: string; private reconnect: number; private resizeTimeout: number; + private backoff: backoff.Backoff; constructor(props) { super(props); @@ -53,6 +55,16 @@ export class Xterm extends Component { this.textDecoder = new TextDecoder(); this.fitAddon = new FitAddon(); this.overlayAddon = new OverlayAddon(); + this.backoff = backoff.exponential({ + initialDelay: 100, + maxDelay: 10000, + }); + this.backoff.on('ready', () => { + this.openTerminal(); + }); + this.backoff.on('backoff', (_, delay: number) => { + console.log(`[ttyd] will attempt to reconnect websocket in ${delay}ms`); + }); } componentDidMount() { @@ -112,6 +124,7 @@ export class Xterm extends Component { socket.onopen = this.onSocketOpen; socket.onmessage = this.onSocketData; socket.onclose = this.onSocketClose; + socket.onerror = this.onSocketError; terminal.loadAddon(fitAddon); terminal.loadAddon(overlayAddon); @@ -141,6 +154,7 @@ export class Xterm extends Component { @bind private onSocketOpen() { console.log('[ttyd] Websocket connection opened'); + this.backoff.reset(); const { socket, textEncoder, fitAddon } = this; const authToken = window.tty_auth_token; @@ -166,6 +180,11 @@ export class Xterm extends Component { } } + @bind + private onSocketError() { + this.backoff.backoff(); + } + @bind private onSocketData(event: MessageEvent) { const { terminal, textDecoder, zmodemAddon } = this; diff --git a/html/yarn.lock b/html/yarn.lock index 8c5287d..33b6df9 100644 --- a/html/yarn.lock +++ b/html/yarn.lock @@ -685,6 +685,13 @@ bach@^1.0.0: async-settle "^1.0.0" now-and-later "^2.0.0" +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= + dependencies: + precond "0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -6628,6 +6635,11 @@ preact@^8.4.2: resolved "https://registry.yarnpkg.com/preact/-/preact-8.4.2.tgz#1263b974a17d1ea80b66590e41ef786ced5d6a23" integrity sha512-TsINETWiisfB6RTk0wh3/mvxbGRvx+ljeBccZ4Z6MPFKgu/KFGyf2Bmw3Z/jlXhL5JlNKY6QAbA9PVyzIy9//A== +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= + prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" diff --git a/src/index.html b/src/index.html index 2e895df..6e414ba 100644 --- a/src/index.html +++ b/src/index.html @@ -1 +1 @@ -ttyd - Terminal \ No newline at end of file +ttyd - Terminal \ No newline at end of file -- 2.43.4