mirror of https://github.com/OpenVidu/openvidu.git
openvidu-browser: reconnection support for OpenVidu Enterprise
parent
24ba648015
commit
e6b4f23fcf
|
@ -1030,13 +1030,16 @@ export class OpenVidu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private reconnectedCallback(): void {
|
private reconnectWebsocketThroughRpcConnectMethod(rpcSessionId) {
|
||||||
logger.warn('Websocket reconnected');
|
// This RPC method allows checking:
|
||||||
if (this.isRoomAvailable()) {
|
// Single Master: if success, connection recovered
|
||||||
if (!!this.session.connection) {
|
// if error, no Master Node crashed and life will be -1. onLostConnection with reason networkDisconnect will be triggered
|
||||||
// This RPC method allows checking if the WebSocket reconnected to a session where
|
// Multi Master: if success, connection recovered
|
||||||
// the user is still a participant, or the session evicted the user
|
// if error and Master Node crashed notification was already received, nothing must be done
|
||||||
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
|
// if error and Master Node NOT crashed, sessionStatus method must be sent:
|
||||||
|
// if life is equal, networkDisconnect
|
||||||
|
// if life is greater, nodeCrashed
|
||||||
|
this.sendRequest('connect', { sessionId: rpcSessionId, reconnect: true }, (error, response) => {
|
||||||
if (!!error) {
|
if (!!error) {
|
||||||
|
|
||||||
if (this.isMasterNodeCrashed()) {
|
if (this.isMasterNodeCrashed()) {
|
||||||
|
@ -1047,29 +1050,47 @@ export class OpenVidu {
|
||||||
|
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
|
|
||||||
const notifyNetworkDisconnection = (error) => {
|
const notifyLostConnection = (reason, errorMsg) => {
|
||||||
logger.warn('Websocket was able to reconnect to OpenVidu Server, but your Connection was already destroyed due to timeout. You are no longer a participant of the Session and your media streams have been destroyed');
|
logger.warn(errorMsg);
|
||||||
this.session.onLostConnection("networkDisconnect");
|
this.session.onLostConnection(reason);
|
||||||
this.jsonRpcClient.close(4101, "Reconnection fault");
|
this.jsonRpcClient.close(4101, "Reconnection fault: " + errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rpcSessionStatus = () => {
|
||||||
if (this.life === -1) {
|
if (this.life === -1) {
|
||||||
notifyNetworkDisconnection(error);
|
// Single Master
|
||||||
|
notifyLostConnection('networkDisconnect', 'WS successfully reconnected but the user was already evicted due to timeout');
|
||||||
} else {
|
} else {
|
||||||
|
// Multi Master
|
||||||
// This RPC method is only required to find out the reason of the disconnection:
|
// This RPC method is only required to find out the reason of the disconnection:
|
||||||
// whether the client lost its network connection or a Master Node crashed
|
// whether the client lost its network connection or a Master Node crashed
|
||||||
this.sendRequest('sessionStatus', { sessionId: this.session.sessionId }, (error, response) => {
|
this.sendRequest('sessionStatus', { sessionId: this.session.sessionId }, (error, response) => {
|
||||||
|
if (error != null) {
|
||||||
|
console.error('Error checking session status', error);
|
||||||
|
} else {
|
||||||
if (this.life === response.life) {
|
if (this.life === response.life) {
|
||||||
// If the life stored in the client matches the life stored in the server, it means that the client lost its network connection
|
// If the life stored in the client matches the life stored in the server, it means that the client lost its network connection
|
||||||
notifyNetworkDisconnection(error);
|
notifyLostConnection('networkDisconnect', 'WS successfully reconnected but the user was already evicted due to timeout');
|
||||||
} else {
|
} else {
|
||||||
// If the life stored in the client is below the life stored in the server, it means that the Master Node has crashed
|
// If the life stored in the client is below the life stored in the server, it means that the Master Node has crashed
|
||||||
logger.warn('Websocket was able to reconnect to OpenVidu Server, but your Master Node crashed.');
|
notifyLostConnection('nodeCrashed', 'WS successfully reconnected to OpenVidu Server but your Master Node crashed');
|
||||||
this.session.onLostConnection("nodeCrashed");
|
}
|
||||||
this.jsonRpcClient.close(4101, "Reconnection fault");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (error.code === 40007 && error.message === 'reconnection error') {
|
||||||
|
// Kurento error: invalid RPC sessionId. This means that the kurento-jsonrpc-server of openvidu-server where kurento-jsonrpc-client
|
||||||
|
// is trying to reconnect does not know about this sessionId. This can mean two things:
|
||||||
|
// 1) openvidu-browser managed to reconnect after a while, but openvidu-server already evicted the user for not receiving ping.
|
||||||
|
// 2) openvidu-server process is a different one because of a node crash.
|
||||||
|
// Send a "sessionStatus" method to check the reason
|
||||||
|
console.error('Invalid RPC sessionId. Client network disconnection or Master Node crash');
|
||||||
|
rpcSessionStatus();
|
||||||
|
} else {
|
||||||
|
rpcSessionStatus();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1077,6 +1098,13 @@ export class OpenVidu {
|
||||||
this.session.onRecoveredConnection();
|
this.session.onRecoveredConnection();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private reconnectedCallback(): void {
|
||||||
|
logger.warn('Websocket reconnected');
|
||||||
|
if (this.isRoomAvailable()) {
|
||||||
|
if (!!this.session.connection) {
|
||||||
|
this.reconnectWebsocketThroughRpcConnectMethod(this.session.connection.rpcSessionId);
|
||||||
} else {
|
} else {
|
||||||
logger.warn('There was no previous connection when running reconnection callback');
|
logger.warn('There was no previous connection when running reconnection callback');
|
||||||
// Make Session object dispatch 'sessionDisconnected' event
|
// Make Session object dispatch 'sessionDisconnected' event
|
||||||
|
|
|
@ -100,9 +100,19 @@ function WebSocketWithReconnection(config) {
|
||||||
reconnectAux(maxRetries, numRetries);
|
reconnectAux(maxRetries, numRetries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addReconnectionQueryParamsIfMissing(uriString) {
|
||||||
|
var searchParams = new URLSearchParams((new URL(uriString)).search);
|
||||||
|
if (!searchParams.has("reconnect")) {
|
||||||
|
uriString = (Array.from(searchParams).length > 0) ? (uriString + '&reconnect=true') : (uriString + '?reconnect=true');
|
||||||
|
}
|
||||||
|
return uriString;
|
||||||
|
}
|
||||||
|
|
||||||
function reconnectAux(maxRetries, numRetries) {
|
function reconnectAux(maxRetries, numRetries) {
|
||||||
Logger.debug("Reconnection attempt #" + numRetries);
|
Logger.debug("Reconnection attempt #" + numRetries);
|
||||||
ws.close(4104, 'Connection closed for reconnection');
|
ws.close(4104, 'Connection closed for reconnection');
|
||||||
|
|
||||||
|
wsUri = addReconnectionQueryParamsIfMissing(wsUri);
|
||||||
ws = new WebSocket(wsUri);
|
ws = new WebSocket(wsUri);
|
||||||
|
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
|
|
Loading…
Reference in New Issue