Wrap all websocket errors, reconnect earlier

This commit is contained in:
Fedor Indutny 2021-06-14 17:12:58 -07:00 committed by GitHub
parent 8f5086227a
commit 584cedecff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 3 deletions

View file

@ -225,6 +225,20 @@ describe('WebSocket-Resource', () => {
this.clock.next();
});
it('optionally disconnects if suspended', function thisNeeded1(done) {
const socket = new FakeSocket();
sinon.stub(socket, 'close').callsFake(() => done());
new WebSocketResource(socket as WebSocket, {
keepalive: true,
});
// Just skip one hour immediately
this.clock.setSystemTime(NOW + 3600 * 1000);
this.clock.next();
});
it('allows resetting the keepalive timer', function thisNeeded2(done) {
const startTime = Date.now();

View file

@ -336,9 +336,18 @@ async function _connectSocket(
reject(translatedError);
});
client.on('connectFailed', error => {
client.on('connectFailed', e => {
clearTimeout(timer);
reject(error);
reject(
makeHTTPError(
'_connectSocket connectFailed',
0,
{},
e.toString(),
stack
)
);
});
});
}

View file

@ -34,6 +34,8 @@ import { typedArrayToArrayBuffer as toArrayBuffer } from '../Crypto';
import EventTarget from './EventTarget';
import { isOlderThan } from '../util/timestamp';
class Request {
verb: string;
@ -264,6 +266,10 @@ type KeepAliveOptionsType = {
disconnect?: boolean;
};
const KEEPALIVE_INTERVAL_MS = 55000; // 55 seconds + 5 seconds for closing the
// socket above.
const MAX_KEEPALIVE_INTERVAL_MS = 300 * 1000; // 5 minutes
class KeepAlive {
private keepAliveTimer: NodeJS.Timeout | undefined;
@ -275,6 +281,8 @@ class KeepAlive {
private wsr: WebSocketResource;
private lastAliveAt: number = Date.now();
constructor(
websocketResource: WebSocketResource,
opts: KeepAliveOptionsType = {}
@ -295,9 +303,19 @@ class KeepAlive {
public send(): void {
this.clearTimers();
if (isOlderThan(this.lastAliveAt, MAX_KEEPALIVE_INTERVAL_MS)) {
window.log.info('WebSocketResources: disconnecting due to stale state');
this.wsr.close(
3001,
`Last keepalive request was too far in the past: ${this.lastAliveAt}`
);
return;
}
if (this.disconnect) {
// automatically disconnect if server doesn't ack
this.disconnectTimer = setTimeout(() => {
window.log.info('WebSocketResources: disconnecting due to no response');
this.clearTimers();
this.wsr.close(3001, 'No response to keepalive request');
@ -315,9 +333,11 @@ class KeepAlive {
}
public reset(): void {
this.lastAliveAt = Date.now();
this.clearTimers();
this.keepAliveTimer = setTimeout(() => this.send(), 55000);
this.keepAliveTimer = setTimeout(() => this.send(), KEEPALIVE_INTERVAL_MS);
}
private clearTimers(): void {