[FIX] web_editor: retry peer to peer connection with exponential backoff
When there is a problem in the peer to peer network where we try to recover a connection, retry with exponential backoff instead of potentially spamming the server indefinitely. task-3164011 closes odoo/odoo#111802 X-original-commit: fd97295c9cf8b1b0c800f407bb5f538f78cc2665 Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
committed by
David Monjoie
parent
5cb4175e9c
commit
071ca078b5
@@ -379,6 +379,7 @@ export class PeerToPeer {
|
||||
this.clientsInfos[clientId] = {
|
||||
makingOffer: false,
|
||||
iceCandidateBuffer: [],
|
||||
backoffFactor: 0,
|
||||
};
|
||||
const pc = new RTCPeerConnection(this.options.peerConnectionConfig);
|
||||
|
||||
@@ -429,6 +430,9 @@ export class PeerToPeer {
|
||||
reason: 'ice connection disconnected',
|
||||
});
|
||||
break;
|
||||
case 'connected':
|
||||
this.clientsInfos[clientId].backoffFactor = 0;
|
||||
break;
|
||||
}
|
||||
};
|
||||
// This event does not work in FF. Let's try with oniceconnectionstatechange if it is sufficient.
|
||||
@@ -446,6 +450,10 @@ export class PeerToPeer {
|
||||
reason: 'connection disconnected',
|
||||
});
|
||||
break;
|
||||
case 'connected':
|
||||
case 'completed':
|
||||
this.clientsInfos[clientId].backoffFactor = 0;
|
||||
break;
|
||||
}
|
||||
};
|
||||
pc.onicecandidateerror = async error => {
|
||||
@@ -505,7 +513,7 @@ export class PeerToPeer {
|
||||
if (!dataChannel || dataChannel.readyState !== 'open') {
|
||||
if (clientInfo && !clientInfo.zombieTimeout) {
|
||||
if (debugShowLog) console.warn(
|
||||
`Impossible to communicate with client ${clientId}. The connection be killed in 10 seconds if the datachannel state has not changed.`,
|
||||
`Impossible to communicate with client ${clientId}. The connection will be killed in 10 seconds if the datachannel state has not changed.`,
|
||||
);
|
||||
this._killPotentialZombie(clientId);
|
||||
}
|
||||
@@ -563,6 +571,18 @@ export class PeerToPeer {
|
||||
}
|
||||
const clientInfos = this.clientsInfos[clientId];
|
||||
if (!clientInfos || clientInfos.fallbackTimeout) return;
|
||||
const backoffFactor = this.clientsInfos[clientId].backoffFactor;
|
||||
const backoffDelay = delay * Math.pow(2, backoffFactor);
|
||||
// Stop trying to recover the connection after 10 attempts.
|
||||
if (backoffFactor > 10) {
|
||||
if (debugShowLog) {
|
||||
console.log(
|
||||
`%c STOP RTC RECOVERY: impossible to connect to client ${clientId}: ${reason}`,
|
||||
'background: darkred; color: white;',
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
clientInfos.fallbackTimeout = setTimeout(async () => {
|
||||
clientInfos.fallbackTimeout = undefined;
|
||||
@@ -576,12 +596,13 @@ export class PeerToPeer {
|
||||
// hard reset: recreating a RTCPeerConnection
|
||||
if (debugShowLog)
|
||||
console.log(
|
||||
`%c RTC RECOVERY: calling back client ${clientId} to salvage the connection ${pc.iceConnectionState}, reason: ${reason}`,
|
||||
`%c RTC RECOVERY: calling back client ${clientId} to salvage the connection ${pc.iceConnectionState} after ${backoffDelay}ms, reason: ${reason}`,
|
||||
'background: darkorange; color: white;',
|
||||
);
|
||||
this.removeClient(clientId);
|
||||
await this._createClient(clientId);
|
||||
}, delay);
|
||||
const newClientInfos = this._createClient(clientId);
|
||||
newClientInfos.backoffFactor = backoffFactor + 1;
|
||||
}, backoffDelay);
|
||||
}
|
||||
// todo: do we try to salvage the connection after killing the zombie ?
|
||||
// Maybe the salvage should be done when the connection is dropped.
|
||||
|
||||
Reference in New Issue
Block a user