Socket request timeout handling, with retries.

auto_join_3.3
Håvar Aambø Fosstveit 2020-05-19 14:09:27 +02:00
parent b0e57756cb
commit 0f184a3a29
6 changed files with 109 additions and 12 deletions

View File

@ -37,7 +37,8 @@ var config =
'opera'
],
// Socket.io request timeout
requestTimeout : 10000,
requestTimeout : 20000,
requestRetries : 3,
transportOptions :
{
tcp : true

View File

@ -1,6 +1,7 @@
import Logger from './Logger';
import hark from 'hark';
import { getSignalingUrl } from './urlFactory';
import { SocketTimeoutError } from './utils';
import * as requestActions from './actions/requestActions';
import * as meActions from './actions/meActions';
import * as roomActions from './actions/roomActions';
@ -574,7 +575,7 @@ export default class RoomClient
if (called)
return;
called = true;
callback(new Error('Request timeout.'));
callback(new SocketTimeoutError('Request timed out'));
},
ROOM_OPTIONS.requestTimeout
);
@ -590,13 +591,13 @@ export default class RoomClient
};
}
sendRequest(method, data)
_sendRequest(method, data)
{
return new Promise((resolve, reject) =>
{
if (!this._signalingSocket)
{
reject('No socket connection.');
reject('No socket connection');
}
else
{
@ -606,19 +607,42 @@ export default class RoomClient
this.timeoutCallback((err, response) =>
{
if (err)
{
reject(err);
}
else
{
resolve(response);
}
})
);
}
});
}
async sendRequest(method, data)
{
logger.debug('sendRequest() [method:"%s", data:"%o"]', method, data);
const {
requestRetries = 3
} = window.config;
for (let tries = 0; tries < requestRetries; tries++)
{
try
{
return await this._sendRequest(method, data);
}
catch (error)
{
if (
error instanceof SocketTimeoutError &&
tries < requestRetries
)
logger.warn('sendRequest() | timeout, retrying [attempt:"%s"]', tries);
else
throw error;
}
}
}
async changeDisplayName(displayName)
{
logger.debug('changeDisplayName() [displayName:"%s"]', displayName);

View File

@ -16,4 +16,22 @@ export const idle = (callback, delay) =>
handle = setTimeout(callback, delay);
};
};
};
/**
* Error produced when a socket request has a timeout.
*/
export class SocketTimeoutError extends Error
{
constructor(message)
{
super(message);
this.name = 'SocketTimeoutError';
if (Error.hasOwnProperty('captureStackTrace')) // Just in V8.
Error.captureStackTrace(this, SocketTimeoutError);
else
this.stack = (new Error(message)).stack;
}
}

View File

@ -276,6 +276,10 @@ module.exports =
// maxUsersPerRoom : 20,
// Room size before spreading to new router
routerScaleSize : 40,
// Socket timout value
requestTimeout : 20000,
// Socket retries when timeout
requestRetries : 3,
// Mediasoup settings
mediasoup :
{

View File

@ -3,6 +3,7 @@ const AwaitQueue = require('awaitqueue');
const axios = require('axios');
const Logger = require('./Logger');
const Lobby = require('./Lobby');
const { SocketTimeoutError } = require('./errors');
const { v4: uuidv4 } = require('uuid');
const jwt = require('jsonwebtoken');
const userRoles = require('../userRoles');
@ -1759,9 +1760,9 @@ class Room extends EventEmitter
if (called)
return;
called = true;
callback(new Error('Request timeout.'));
callback(new SocketTimeoutError('Request timed out'));
},
10000
config.requestTimeout || 20000
);
return (...args) =>
@ -1775,7 +1776,7 @@ class Room extends EventEmitter
};
}
_request(socket, method, data = {})
_sendRequest(socket, method, data = {})
{
return new Promise((resolve, reject) =>
{
@ -1797,6 +1798,33 @@ class Room extends EventEmitter
});
}
async _request(socket, method, data)
{
logger.debug('_request() [method:"%s", data:"%o"]', method, data);
const {
requestRetries = 3
} = config;
for (let tries = 0; tries < requestRetries; tries++)
{
try
{
return await this._sendRequest(socket, method, data);
}
catch (error)
{
if (
error instanceof SocketTimeoutError &&
tries < requestRetries
)
logger.warn('_request() | timeout, retrying [attempt:"%s"]', tries);
else
throw error;
}
}
}
_notification(socket, method, data = {}, broadcast = false, includeSender = false)
{
if (broadcast)

View File

@ -0,0 +1,22 @@
/**
* Error produced when a socket request has a timeout.
*/
class SocketTimeoutError extends Error
{
constructor(message)
{
super(message);
this.name = 'SocketTimeoutError';
if (Error.hasOwnProperty('captureStackTrace')) // Just in V8.
Error.captureStackTrace(this, SocketTimeoutError);
else
this.stack = (new Error(message)).stack;
}
}
module.exports =
{
SocketTimeoutError
};